remeda
Version:
A utility library for JavaScript and Typescript.
1 lines • 4.4 kB
Source Map (JSON)
{"version":3,"file":"mergeDeep.cjs","names":["purry","isPlainObject"],"sources":["../src/mergeDeep.ts"],"sourcesContent":["import type { MergeDeep } from \"type-fest\";\nimport { isPlainObject } from \"./isPlainObject\";\nimport { purry } from \"./purry\";\n\n/**\n * Merges the `source` object into the `destination` object. The merge is similar to performing `{ ...destination, ... source }` (where disjoint values from each object would be copied as-is, and for any overlapping props the value from `source` would be used); But for *each prop* (`p`), if **both** `destination` and `source` have a **plain-object** as a value, the value would be taken as the result of recursively deepMerging them (`result.p === deepMerge(destination.p, source.p)`).\n *\n * @param destination - The object to merge into. In general, this object would have it's values overridden.\n * @param source - The object to merge from. In general, shared keys would be taken from this object.\n * @returns The merged object.\n * @signature\n * R.mergeDeep(destination, source)\n * @example\n * R.mergeDeep({ foo: 'bar', x: 1 }, { foo: 'baz', y: 2 }) // => { foo: 'baz', x: 1, y: 2 }\n * @dataFirst\n * @category Object\n */\nexport function mergeDeep<Destination extends object, Source extends object>(\n destination: Destination,\n source: Source,\n): MergeDeep<Destination, Source>;\n\n/**\n * Merges the `source` object into the `destination` object. The merge is similar to performing `{ ...destination, ... source }` (where disjoint values from each object would be copied as-is, and for any overlapping props the value from `source` would be used); But for *each prop* (`p`), if **both** `destination` and `source` have a **plain-object** as a value, the value would be taken as the result of recursively deepMerging them (`result.p === deepMerge(destination.p, source.p)`).\n *\n * @param source - The object to merge from. In general, shared keys would be taken from this object.\n * @returns The merged object.\n * @signature\n * R.mergeDeep(source)(destination)\n * @example\n * R.pipe(\n * { foo: 'bar', x: 1 },\n * R.mergeDeep({ foo: 'baz', y: 2 }),\n * ); // => { foo: 'baz', x: 1, y: 2 }\n * @dataLast\n * @category Object\n */\nexport function mergeDeep<Source extends object>(\n source: Source,\n): <Destination extends object>(\n target: Destination,\n) => MergeDeep<Destination, Source>;\n\nexport function mergeDeep(...args: ReadonlyArray<unknown>): unknown {\n return purry(mergeDeepImplementation, args);\n}\n\nfunction mergeDeepImplementation<\n Destination extends object,\n Source extends object,\n>(destination: Destination, source: Source): MergeDeep<Destination, Source> {\n // At this point the output is already merged, simply not deeply merged.\n const output = { ...destination, ...source } as Record<\n keyof Destination | keyof Source,\n unknown\n >;\n\n // now just scan the output and look for values that should have been deep-\n // merged\n for (const key in source) {\n if (!(key in destination)) {\n // They don't share this key.\n continue;\n }\n\n const { [key]: destinationValue } = destination;\n if (!isPlainObject(destinationValue)) {\n // The value in destination is not a mergable object so the value from\n // source (which was already copied in the shallow merge) would be used\n // as-is.\n continue;\n }\n\n const { [key]: sourceValue } = source;\n if (!isPlainObject(sourceValue)) {\n // The value in source is not a mergable object either, so it will\n // override the object in destination.\n continue;\n }\n\n // Both destination and source have a mergable object for this key, so we\n // recursively merge them.\n output[key] = mergeDeepImplementation(destinationValue, sourceValue);\n }\n\n // @ts-expect-error [ts2322] - We build the output object iteratively, I don't think it's possible to improve the types here so that typescript infers the right type.\n return output;\n}\n"],"mappings":"yEA2CA,SAAgB,EAAU,GAAG,EAAuC,CAClE,OAAOA,EAAAA,EAAM,EAAyB,EAAK,CAG7C,SAAS,EAGP,EAA0B,EAAgD,CAE1E,IAAM,EAAS,CAAE,GAAG,EAAa,GAAG,EAAQ,CAO5C,IAAK,IAAM,KAAO,EAAQ,CACxB,GAAI,EAAE,KAAO,GAEX,SAGF,GAAM,EAAG,GAAM,GAAqB,EACpC,GAAI,CAACC,EAAAA,cAAc,EAAiB,CAIlC,SAGF,GAAM,EAAG,GAAM,GAAgB,EAC1BA,EAAAA,cAAc,EAAY,GAQ/B,EAAO,GAAO,EAAwB,EAAkB,EAAY,EAItE,OAAO"}