UNPKG

6.83 kBSource Map (JSON)View Raw
1{"version":3,"file":"mergeDeep.js","sourceRoot":"","sources":["../../../src/utilities/common/mergeDeep.ts"],"names":[],"mappings":"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","sourcesContent":["import { isNonNullObject } from \"./objects\";\n\nconst { hasOwnProperty } = Object.prototype;\n\n// These mergeDeep and mergeDeepArray utilities merge any number of objects\n// together, sharing as much memory as possible with the source objects, while\n// remaining careful to avoid modifying any source objects.\n\n// Logically, the return type of mergeDeep should be the intersection of\n// all the argument types. The binary call signature is by far the most\n// common, but we support 0- through 5-ary as well. After that, the\n// resulting type is just the inferred array element type. Note to nerds:\n// there is a more clever way of doing this that converts the tuple type\n// first to a union type (easy enough: T[number]) and then converts the\n// union to an intersection type using distributive conditional type\n// inference, but that approach has several fatal flaws (boolean becomes\n// true & false, and the inferred type ends up as unknown in many cases),\n// in addition to being nearly impossible to explain/understand.\nexport type TupleToIntersection<T extends any[]> =\n T extends [infer A] ? A :\n T extends [infer A, infer B] ? A & B :\n T extends [infer A, infer B, infer C] ? A & B & C :\n T extends [infer A, infer B, infer C, infer D] ? A & B & C & D :\n T extends [infer A, infer B, infer C, infer D, infer E] ? A & B & C & D & E :\n T extends (infer U)[] ? U : any;\n\nexport function mergeDeep<T extends any[]>(\n ...sources: T\n): TupleToIntersection<T> {\n return mergeDeepArray(sources);\n}\n\n// In almost any situation where you could succeed in getting the\n// TypeScript compiler to infer a tuple type for the sources array, you\n// could just use mergeDeep instead of mergeDeepArray, so instead of\n// trying to convert T[] to an intersection type we just infer the array\n// element type, which works perfectly when the sources array has a\n// consistent element type.\nexport function mergeDeepArray<T>(sources: T[]): T {\n let target = sources[0] || ({} as T);\n const count = sources.length;\n if (count > 1) {\n const merger = new DeepMerger();\n for (let i = 1; i < count; ++i) {\n target = merger.merge(target, sources[i]);\n }\n }\n return target;\n}\n\nexport type ReconcilerFunction<TContextArgs extends any[]> = (\n this: DeepMerger<TContextArgs>,\n target: Record<string | number, any>,\n source: Record<string | number, any>,\n property: string | number,\n ...context: TContextArgs\n) => any;\n\nconst defaultReconciler: ReconcilerFunction<any[]> =\n function (target, source, property) {\n return this.merge(target[property], source[property]);\n };\n\nexport class DeepMerger<TContextArgs extends any[]> {\n constructor(\n private reconciler: ReconcilerFunction<TContextArgs> = defaultReconciler,\n ) {}\n\n public merge(target: any, source: any, ...context: TContextArgs): any {\n if (isNonNullObject(source) && isNonNullObject(target)) {\n Object.keys(source).forEach(sourceKey => {\n if (hasOwnProperty.call(target, sourceKey)) {\n const targetValue = target[sourceKey];\n if (source[sourceKey] !== targetValue) {\n const result = this.reconciler(target, source, sourceKey, ...context);\n // A well-implemented reconciler may return targetValue to indicate\n // the merge changed nothing about the structure of the target.\n if (result !== targetValue) {\n target = this.shallowCopyForMerge(target);\n target[sourceKey] = result;\n }\n }\n } else {\n // If there is no collision, the target can safely share memory with\n // the source, and the recursion can terminate here.\n target = this.shallowCopyForMerge(target);\n target[sourceKey] = source[sourceKey];\n }\n });\n\n return target;\n }\n\n // If source (or target) is not an object, let source replace target.\n return source;\n }\n\n public isObject = isNonNullObject;\n\n private pastCopies = new Set<any>();\n\n public shallowCopyForMerge<T>(value: T): T {\n if (isNonNullObject(value)) {\n if (!this.pastCopies.has(value)) {\n if (Array.isArray(value)) {\n value = (value as any).slice(0);\n } else {\n value = {\n __proto__: Object.getPrototypeOf(value),\n ...value,\n };\n }\n this.pastCopies.add(value);\n }\n }\n return value;\n }\n}\n"]}
\No newline at end of file