UNPKG

3.62 kBJavaScriptView Raw
1import { __assign, __spreadArray } from "tslib";
2import { isNonNullObject } from "./objects.js";
3var hasOwnProperty = Object.prototype.hasOwnProperty;
4export function mergeDeep() {
5 var sources = [];
6 for (var _i = 0; _i < arguments.length; _i++) {
7 sources[_i] = arguments[_i];
8 }
9 return mergeDeepArray(sources);
10}
11// In almost any situation where you could succeed in getting the
12// TypeScript compiler to infer a tuple type for the sources array, you
13// could just use mergeDeep instead of mergeDeepArray, so instead of
14// trying to convert T[] to an intersection type we just infer the array
15// element type, which works perfectly when the sources array has a
16// consistent element type.
17export function mergeDeepArray(sources) {
18 var target = sources[0] || {};
19 var count = sources.length;
20 if (count > 1) {
21 var merger = new DeepMerger();
22 for (var i = 1; i < count; ++i) {
23 target = merger.merge(target, sources[i]);
24 }
25 }
26 return target;
27}
28var defaultReconciler = function (target, source, property) {
29 return this.merge(target[property], source[property]);
30};
31var DeepMerger = /** @class */ (function () {
32 function DeepMerger(reconciler) {
33 if (reconciler === void 0) { reconciler = defaultReconciler; }
34 this.reconciler = reconciler;
35 this.isObject = isNonNullObject;
36 this.pastCopies = new Set();
37 }
38 DeepMerger.prototype.merge = function (target, source) {
39 var _this = this;
40 var context = [];
41 for (var _i = 2; _i < arguments.length; _i++) {
42 context[_i - 2] = arguments[_i];
43 }
44 if (isNonNullObject(source) && isNonNullObject(target)) {
45 Object.keys(source).forEach(function (sourceKey) {
46 if (hasOwnProperty.call(target, sourceKey)) {
47 var targetValue = target[sourceKey];
48 if (source[sourceKey] !== targetValue) {
49 var result = _this.reconciler.apply(_this, __spreadArray([target,
50 source,
51 sourceKey], context, false));
52 // A well-implemented reconciler may return targetValue to indicate
53 // the merge changed nothing about the structure of the target.
54 if (result !== targetValue) {
55 target = _this.shallowCopyForMerge(target);
56 target[sourceKey] = result;
57 }
58 }
59 }
60 else {
61 // If there is no collision, the target can safely share memory with
62 // the source, and the recursion can terminate here.
63 target = _this.shallowCopyForMerge(target);
64 target[sourceKey] = source[sourceKey];
65 }
66 });
67 return target;
68 }
69 // If source (or target) is not an object, let source replace target.
70 return source;
71 };
72 DeepMerger.prototype.shallowCopyForMerge = function (value) {
73 if (isNonNullObject(value)) {
74 if (!this.pastCopies.has(value)) {
75 if (Array.isArray(value)) {
76 value = value.slice(0);
77 }
78 else {
79 value = __assign({ __proto__: Object.getPrototypeOf(value) }, value);
80 }
81 this.pastCopies.add(value);
82 }
83 }
84 return value;
85 };
86 return DeepMerger;
87}());
88export { DeepMerger };
89//# sourceMappingURL=mergeDeep.js.map
\No newline at end of file