es-toolkit 1.14.0-dev.409 → 1.14.0-dev.410

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,261 @@
1
+ /**
2
+ * Merges the properties of one or more source objects into the target object.
3
+ *
4
+ * This function performs a deep merge, recursively merging nested objects and arrays.
5
+ * If a property in the source object is an array or object and the corresponding property in the target object is also an array or object, they will be merged.
6
+ * If a property in the source object is `undefined`, it will not overwrite a defined property in the target object.
7
+ *
8
+ * You can provide a custom `merge` function to control how properties are merged. The `merge` function is called for each property that is being merged and receives the following arguments:
9
+ *
10
+ * - `targetValue`: The current value of the property in the target object.
11
+ * - `sourceValue`: The value of the property in the source object.
12
+ * - `key`: The key of the property being merged.
13
+ * - `target`: The target object.
14
+ * - `source`: The source object.
15
+ * - `stack`: A `Map` used to keep track of objects that have already been processed to handle circular references.
16
+ *
17
+ * The `merge` function should return the value to be set in the target object. If it returns `undefined`, a default deep merge will be applied for arrays and objects.
18
+ *
19
+ * The function can handle multiple source objects and will merge them all into the target object.
20
+ *
21
+ * @param {T} target - The target object into which the source object properties will be merged. This object is modified in place.
22
+ * @param {S} source - The first source object whose properties will be merged into the target object.
23
+ * @returns {T & S} The updated target object with properties from the source object(s) merged in.
24
+ *
25
+ * @template T - Type of the target object.
26
+ * @template S - Type of the first source object.
27
+ *
28
+ * @example
29
+ * const target = { a: 1, b: 2 };
30
+ * const source = { b: 3, c: 4 };
31
+ *
32
+ * mergeWith(target, source, (targetValue, sourceValue) => {
33
+ * if (typeof targetValue === 'number' && typeof sourceValue === 'number') {
34
+ * return targetValue + sourceValue;
35
+ * }
36
+ * });
37
+ * // Returns { a: 1, b: 5, c: 4 }
38
+ * @example
39
+ * const target = { a: [1], b: [2] };
40
+ * const source = { a: [3], b: [4] };
41
+ *
42
+ * const result = mergeWith(target, source, (objValue, srcValue) => {
43
+ * if (Array.isArray(objValue)) {
44
+ * return objValue.concat(srcValue);
45
+ * }
46
+ * });
47
+ *
48
+ * expect(result).toEqual({ a: [1, 3], b: [2, 4] });
49
+ */
50
+ declare function mergeWith<T, S>(target: T, source: S, merge: (targetValue: any, sourceValue: any, key: string, target: T, source: S, stack: Map<any, any>) => any): T & S;
51
+ /**
52
+ * Merges the properties of one or more source objects into the target object.
53
+ *
54
+ * This function performs a deep merge, recursively merging nested objects and arrays.
55
+ * If a property in the source object is an array or object and the corresponding property in the target object is also an array or object, they will be merged.
56
+ * If a property in the source object is `undefined`, it will not overwrite a defined property in the target object.
57
+ *
58
+ * You can provide a custom `merge` function to control how properties are merged. The `merge` function is called for each property that is being merged and receives the following arguments:
59
+ *
60
+ * - `targetValue`: The current value of the property in the target object.
61
+ * - `sourceValue`: The value of the property in the source object.
62
+ * - `key`: The key of the property being merged.
63
+ * - `target`: The target object.
64
+ * - `source`: The source object.
65
+ * - `stack`: A `Map` used to keep track of objects that have already been processed to handle circular references.
66
+ *
67
+ * The `merge` function should return the value to be set in the target object. If it returns `undefined`, a default deep merge will be applied for arrays and objects.
68
+ *
69
+ * The function can handle multiple source objects and will merge them all into the target object.
70
+ *
71
+ * @param {O} object - The target object into which the source object properties will be merged. This object is modified in place.
72
+ * @param {S1} source1 - The first source object to be merged into the target object.
73
+ * @param {S2} source2 - The second source object to be merged into the target object.
74
+ * @returns {O & S1 & S2} The updated target object with properties from the source objects merged in.
75
+ *
76
+ * @template O - Type of the target object.
77
+ * @template S1 - Type of the first source object.
78
+ * @template S2 - Type of the second source object.
79
+ *
80
+ * @example
81
+ * const target = { a: 1, b: 2 };
82
+ * const source = { b: 3, c: 4 };
83
+ *
84
+ * mergeWith(target, source, (targetValue, sourceValue) => {
85
+ * if (typeof targetValue === 'number' && typeof sourceValue === 'number') {
86
+ * return targetValue + sourceValue;
87
+ * }
88
+ * });
89
+ * // Returns { a: 1, b: 5, c: 4 }
90
+ * @example
91
+ * const target = { a: [1], b: [2] };
92
+ * const source = { a: [3], b: [4] };
93
+ *
94
+ * const result = mergeWith(target, source, (objValue, srcValue) => {
95
+ * if (Array.isArray(objValue)) {
96
+ * return objValue.concat(srcValue);
97
+ * }
98
+ * });
99
+ *
100
+ * expect(result).toEqual({ a: [1, 3], b: [2, 4] });
101
+ */
102
+ declare function mergeWith<O, S1, S2>(object: O, source1: S1, source2: S2, merge: (targetValue: any, sourceValue: any, key: string, target: any, source: any, stack: Map<any, any>) => any): O & S1 & S2;
103
+ /**
104
+ * Merges the properties of one or more source objects into the target object.
105
+ *
106
+ * This function performs a deep merge, recursively merging nested objects and arrays.
107
+ * If a property in the source object is an array or object and the corresponding property in the target object is also an array or object, they will be merged.
108
+ * If a property in the source object is `undefined`, it will not overwrite a defined property in the target object.
109
+ *
110
+ * You can provide a custom `merge` function to control how properties are merged. The `merge` function is called for each property that is being merged and receives the following arguments:
111
+ *
112
+ * - `targetValue`: The current value of the property in the target object.
113
+ * - `sourceValue`: The value of the property in the source object.
114
+ * - `key`: The key of the property being merged.
115
+ * - `target`: The target object.
116
+ * - `source`: The source object.
117
+ * - `stack`: A `Map` used to keep track of objects that have already been processed to handle circular references.
118
+ *
119
+ * The `merge` function should return the value to be set in the target object. If it returns `undefined`, a default deep merge will be applied for arrays and objects.
120
+ *
121
+ * The function can handle multiple source objects and will merge them all into the target object.
122
+ *
123
+ * @param {O} object - The target object into which the source object properties will be merged. This object is modified in place.
124
+ * @param {S1} source1 - The first source object whose properties will be merged into the target object.
125
+ * @param {S2} source2 - The second source object whose properties will be merged into the target object.
126
+ * @param {S3} source3 - The third source object whose properties will be merged into the target object.
127
+ * @returns {O & S1 & S2 & S3} The updated target object with properties from the source object(s) merged in.
128
+ *
129
+ * @template O - Type of the target object.
130
+ * @template S1 - Type of the first source object.
131
+ * @template S2 - Type of the second source object.
132
+ * @template S3 - Type of the third source object.
133
+ *
134
+ * @example
135
+ * const target = { a: 1, b: 2 };
136
+ * const source = { b: 3, c: 4 };
137
+ *
138
+ * mergeWith(target, source, (targetValue, sourceValue) => {
139
+ * if (typeof targetValue === 'number' && typeof sourceValue === 'number') {
140
+ * return targetValue + sourceValue;
141
+ * }
142
+ * });
143
+ * // Returns { a: 1, b: 5, c: 4 }
144
+ * @example
145
+ * const target = { a: [1], b: [2] };
146
+ * const source = { a: [3], b: [4] };
147
+ *
148
+ * const result = mergeWith(target, source, (objValue, srcValue) => {
149
+ * if (Array.isArray(objValue)) {
150
+ * return objValue.concat(srcValue);
151
+ * }
152
+ * });
153
+ *
154
+ * expect(result).toEqual({ a: [1, 3], b: [2, 4] });
155
+ */
156
+ declare function mergeWith<O, S1, S2, S3>(object: O, source1: S1, source2: S2, source3: S3, merge: (targetValue: any, sourceValue: any, key: string, target: any, source: any, stack: Map<any, any>) => any): O & S1 & S2 & S3;
157
+ /**
158
+ * Merges the properties of one or more source objects into the target object.
159
+ *
160
+ * This function performs a deep merge, recursively merging nested objects and arrays.
161
+ * If a property in the source object is an array or object and the corresponding property in the target object is also an array or object, they will be merged.
162
+ * If a property in the source object is `undefined`, it will not overwrite a defined property in the target object.
163
+ *
164
+ * You can provide a custom `merge` function to control how properties are merged. The `merge` function is called for each property that is being merged and receives the following arguments:
165
+ *
166
+ * - `targetValue`: The current value of the property in the target object.
167
+ * - `sourceValue`: The value of the property in the source object.
168
+ * - `key`: The key of the property being merged.
169
+ * - `target`: The target object.
170
+ * - `source`: The source object.
171
+ * - `stack`: A `Map` used to keep track of objects that have already been processed to handle circular references.
172
+ *
173
+ * The `merge` function should return the value to be set in the target object. If it returns `undefined`, a default deep merge will be applied for arrays and objects.
174
+ *
175
+ * The function can handle multiple source objects and will merge them all into the target object.
176
+ *
177
+ * @param {O} object - The target object into which the source object properties will be merged. This object is modified in place.
178
+ * @param {S1} source1 - The first source object whose properties will be merged into the target object.
179
+ * @param {S2} source2 - The second source object whose properties will be merged into the target object.
180
+ * @param {S3} source3 - The third source object whose properties will be merged into the target object.
181
+ * @param {S4} source4 - The fourth source object whose properties will be merged into the target object.
182
+ * @returns {O & S1 & S2 & S3 & S4} The updated target object with properties from the source object(s) merged in.
183
+ *
184
+ * @template O - Type of the target object.
185
+ * @template S1 - Type of the first source object.
186
+ * @template S2 - Type of the second source object.
187
+ * @template S3 - Type of the third source object.
188
+ * @template S4 - Type of the fourth source object.
189
+ *
190
+ * @example
191
+ * const target = { a: 1, b: 2 };
192
+ * const source = { b: 3, c: 4 };
193
+ *
194
+ * mergeWith(target, source, (targetValue, sourceValue) => {
195
+ * if (typeof targetValue === 'number' && typeof sourceValue === 'number') {
196
+ * return targetValue + sourceValue;
197
+ * }
198
+ * });
199
+ * // Returns { a: 1, b: 5, c: 4 }
200
+ * @example
201
+ * const target = { a: [1], b: [2] };
202
+ * const source = { a: [3], b: [4] };
203
+ *
204
+ * const result = mergeWith(target, source, (objValue, srcValue) => {
205
+ * if (Array.isArray(objValue)) {
206
+ * return objValue.concat(srcValue);
207
+ * }
208
+ * });
209
+ *
210
+ * expect(result).toEqual({ a: [1, 3], b: [2, 4] });
211
+ */
212
+ declare function mergeWith<O, S1, S2, S3, S4>(object: O, source1: S1, source2: S2, source3: S3, source4: S4, merge: (targetValue: any, sourceValue: any, key: string, target: any, source: any, stack: Map<any, any>) => any): O & S1 & S2 & S3;
213
+ /**
214
+ * Merges the properties of one or more source objects into the target object.
215
+ *
216
+ * This function performs a deep merge, recursively merging nested objects and arrays.
217
+ * If a property in the source object is an array or object and the corresponding property in the target object is also an array or object, they will be merged.
218
+ * If a property in the source object is `undefined`, it will not overwrite a defined property in the target object.
219
+ *
220
+ * You can provide a custom `merge` function to control how properties are merged. The `merge` function is called for each property that is being merged and receives the following arguments:
221
+ *
222
+ * - `targetValue`: The current value of the property in the target object.
223
+ * - `sourceValue`: The value of the property in the source object.
224
+ * - `key`: The key of the property being merged.
225
+ * - `target`: The target object.
226
+ * - `source`: The source object.
227
+ * - `stack`: A `Map` used to keep track of objects that have already been processed to handle circular references.
228
+ *
229
+ * The `merge` function should return the value to be set in the target object. If it returns `undefined`, a default deep merge will be applied for arrays and objects.
230
+ *
231
+ * The function can handle multiple source objects and will merge them all into the target object.
232
+ *
233
+ * @param {any} any - The target object into which the source object properties will be merged. This object is modified in place.
234
+ * @param {any[]} sources - The source objects whose properties will be merged into the target object.
235
+ * @returns {any} The updated target object with properties from the source object(s) merged in.
236
+ *
237
+ * @example
238
+ * const target = { a: 1, b: 2 };
239
+ * const source = { b: 3, c: 4 };
240
+ *
241
+ * mergeWith(target, source, (targetValue, sourceValue) => {
242
+ * if (typeof targetValue === 'number' && typeof sourceValue === 'number') {
243
+ * return targetValue + sourceValue;
244
+ * }
245
+ * });
246
+ * // Returns { a: 1, b: 5, c: 4 }
247
+ * @example
248
+ * const target = { a: [1], b: [2] };
249
+ * const source = { a: [3], b: [4] };
250
+ *
251
+ * const result = mergeWith(target, source, (objValue, srcValue) => {
252
+ * if (Array.isArray(objValue)) {
253
+ * return objValue.concat(srcValue);
254
+ * }
255
+ * });
256
+ *
257
+ * expect(result).toEqual({ a: [1, 3], b: [2, 4] });
258
+ */
259
+ declare function mergeWith(object: any, ...otherArgs: any[]): any;
260
+
261
+ export { mergeWith };
@@ -0,0 +1,75 @@
1
+ import { clone } from '../../object/clone.mjs';
2
+ import { isArguments } from '../predicate/isArguments.mjs';
3
+ import { isObjectLike } from '../predicate/isObjectLike.mjs';
4
+ import { isPlainObject } from '../predicate/isPlainObject.mjs';
5
+ import { isTypedArray } from '../predicate/isTypedArray.mjs';
6
+ import { cloneDeep } from './cloneDeep.mjs';
7
+
8
+ function mergeWith(object, ...otherArgs) {
9
+ const sources = otherArgs.slice(0, -1);
10
+ const merge = otherArgs[otherArgs.length - 1];
11
+ let result = object;
12
+ for (let i = 0; i < sources.length; i++) {
13
+ const source = sources[i];
14
+ result = mergeWithDeep(object, source, merge, new Map());
15
+ }
16
+ return result;
17
+ }
18
+ function mergeWithDeep(target, source, merge, stack) {
19
+ if (source == null || typeof source !== 'object') {
20
+ return target;
21
+ }
22
+ if (stack.has(source)) {
23
+ return clone(stack.get(source));
24
+ }
25
+ stack.set(source, target);
26
+ if (Array.isArray(source)) {
27
+ source = source.slice();
28
+ for (let i = 0; i < source.length; i++) {
29
+ source[i] = source[i] ?? undefined;
30
+ }
31
+ }
32
+ const sourceKeys = Object.keys(source);
33
+ for (let i = 0; i < sourceKeys.length; i++) {
34
+ const key = sourceKeys[i];
35
+ let sourceValue = source[key];
36
+ let targetValue = target[key];
37
+ if (isArguments(sourceValue)) {
38
+ sourceValue = { ...sourceValue };
39
+ }
40
+ if (isArguments(targetValue)) {
41
+ targetValue = { ...targetValue };
42
+ }
43
+ if (typeof Buffer !== 'undefined' && Buffer.isBuffer(sourceValue)) {
44
+ sourceValue = cloneDeep(sourceValue);
45
+ }
46
+ if (Array.isArray(sourceValue)) {
47
+ targetValue = typeof targetValue === 'object' ? Array.from(targetValue ?? []) : [];
48
+ }
49
+ const merged = merge(targetValue, sourceValue, key, target, source, stack);
50
+ if (merged != null) {
51
+ target[key] = merged;
52
+ }
53
+ else if (Array.isArray(sourceValue)) {
54
+ target[key] = mergeWithDeep(targetValue, sourceValue, merge, stack);
55
+ }
56
+ else if (isObjectLike(targetValue) && isObjectLike(sourceValue)) {
57
+ target[key] = mergeWithDeep(targetValue, sourceValue, merge, stack);
58
+ }
59
+ else if (targetValue == null && Array.isArray(sourceValue)) {
60
+ target[key] = mergeWithDeep([], sourceValue, merge, stack);
61
+ }
62
+ else if (targetValue == null && isPlainObject(sourceValue)) {
63
+ target[key] = mergeWithDeep({}, sourceValue, merge, stack);
64
+ }
65
+ else if (targetValue == null && isTypedArray(sourceValue)) {
66
+ target[key] = cloneDeep(sourceValue);
67
+ }
68
+ else if (targetValue === undefined || sourceValue !== undefined) {
69
+ target[key] = sourceValue;
70
+ }
71
+ }
72
+ return target;
73
+ }
74
+
75
+ export { mergeWith };
package/dist/index.d.mts CHANGED
@@ -82,6 +82,7 @@ export { mapKeys } from './object/mapKeys.mjs';
82
82
  export { mapValues } from './object/mapValues.mjs';
83
83
  export { cloneDeep } from './object/cloneDeep.mjs';
84
84
  export { merge } from './object/merge.mjs';
85
+ export { mergeWith } from './object/mergeWith.mjs';
85
86
  export { isEqual } from './predicate/isEqual.mjs';
86
87
  export { isNil } from './predicate/isNil.mjs';
87
88
  export { isNotNil } from './predicate/isNotNil.mjs';
package/dist/index.d.ts CHANGED
@@ -82,6 +82,7 @@ export { mapKeys } from './object/mapKeys.js';
82
82
  export { mapValues } from './object/mapValues.js';
83
83
  export { cloneDeep } from './object/cloneDeep.js';
84
84
  export { merge } from './object/merge.js';
85
+ export { mergeWith } from './object/mergeWith.js';
85
86
  export { isEqual } from './predicate/isEqual.js';
86
87
  export { isNil } from './predicate/isNil.js';
87
88
  export { isNotNil } from './predicate/isNotNil.js';
package/dist/index.js CHANGED
@@ -103,6 +103,7 @@ exports.omitBy = isObjectLike.omitBy;
103
103
  exports.pick = isObjectLike.pick;
104
104
  exports.pickBy = isObjectLike.pickBy;
105
105
  exports.merge = object_index.merge;
106
+ exports.mergeWith = object_index.mergeWith;
106
107
  exports.isEqual = isSymbol.isEqual;
107
108
  exports.isFunction = isSymbol.isFunction;
108
109
  exports.isLength = isSymbol.isLength;
package/dist/index.mjs CHANGED
@@ -82,6 +82,7 @@ export { mapKeys } from './object/mapKeys.mjs';
82
82
  export { mapValues } from './object/mapValues.mjs';
83
83
  export { cloneDeep } from './object/cloneDeep.mjs';
84
84
  export { merge } from './object/merge.mjs';
85
+ export { mergeWith } from './object/mergeWith.mjs';
85
86
  export { isEqual } from './predicate/isEqual.mjs';
86
87
  export { isNil } from './predicate/isNil.mjs';
87
88
  export { isNotNil } from './predicate/isNotNil.mjs';
@@ -9,3 +9,4 @@ export { mapKeys } from './mapKeys.mjs';
9
9
  export { mapValues } from './mapValues.mjs';
10
10
  export { cloneDeep } from './cloneDeep.mjs';
11
11
  export { merge } from './merge.mjs';
12
+ export { mergeWith } from './mergeWith.mjs';
@@ -9,3 +9,4 @@ export { mapKeys } from './mapKeys.js';
9
9
  export { mapValues } from './mapValues.js';
10
10
  export { cloneDeep } from './cloneDeep.js';
11
11
  export { merge } from './merge.js';
12
+ export { mergeWith } from './mergeWith.js';
@@ -23,6 +23,29 @@ function merge(target, source) {
23
23
  return target;
24
24
  }
25
25
 
26
+ function mergeWith(target, source, merge) {
27
+ const sourceKeys = Object.keys(source);
28
+ for (let i = 0; i < sourceKeys.length; i++) {
29
+ const key = sourceKeys[i];
30
+ const sourceValue = source[key];
31
+ const targetValue = target[key];
32
+ const merged = merge(targetValue, sourceValue, key, target, source);
33
+ if (merged != null) {
34
+ target[key] = merged;
35
+ }
36
+ else if (Array.isArray(sourceValue)) {
37
+ target[key] = mergeWith(targetValue ?? [], sourceValue, merge);
38
+ }
39
+ else if (isObjectLike.isObjectLike(targetValue) && isObjectLike.isObjectLike(sourceValue)) {
40
+ target[key] = mergeWith(targetValue ?? {}, sourceValue, merge);
41
+ }
42
+ else if (targetValue === undefined || sourceValue !== undefined) {
43
+ target[key] = sourceValue;
44
+ }
45
+ }
46
+ return target;
47
+ }
48
+
26
49
  exports.clone = isObjectLike.clone;
27
50
  exports.cloneDeep = isObjectLike.cloneDeep;
28
51
  exports.flattenObject = isObjectLike.flattenObject;
@@ -34,3 +57,4 @@ exports.omitBy = isObjectLike.omitBy;
34
57
  exports.pick = isObjectLike.pick;
35
58
  exports.pickBy = isObjectLike.pickBy;
36
59
  exports.merge = merge;
60
+ exports.mergeWith = mergeWith;
@@ -9,3 +9,4 @@ export { mapKeys } from './mapKeys.mjs';
9
9
  export { mapValues } from './mapValues.mjs';
10
10
  export { cloneDeep } from './cloneDeep.mjs';
11
11
  export { merge } from './merge.mjs';
12
+ export { mergeWith } from './mergeWith.mjs';
@@ -5,6 +5,8 @@
5
5
  * If a property in the source object is an array or an object and the corresponding property in the target object is also an array or object, they will be merged.
6
6
  * If a property in the source object is undefined, it will not overwrite a defined property in the target object.
7
7
  *
8
+ * Note that this function mutates the target object.
9
+ *
8
10
  * @param {T} target - The target object into which the source object properties will be merged. This object is modified in place.
9
11
  * @param {S} source - The source object whose properties will be merged into the target object.
10
12
  * @returns {T & S} The updated target object with properties from the source object merged in.
@@ -5,6 +5,8 @@
5
5
  * If a property in the source object is an array or an object and the corresponding property in the target object is also an array or object, they will be merged.
6
6
  * If a property in the source object is undefined, it will not overwrite a defined property in the target object.
7
7
  *
8
+ * Note that this function mutates the target object.
9
+ *
8
10
  * @param {T} target - The target object into which the source object properties will be merged. This object is modified in place.
9
11
  * @param {S} source - The source object whose properties will be merged into the target object.
10
12
  * @returns {T & S} The updated target object with properties from the source object merged in.
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Merges the properties of the source object into the target object.
3
+ *
4
+ * You can provide a custom `merge` function to control how properties are merged. The `merge` function is called for each property that is being merged and receives the following arguments:
5
+ *
6
+ * - `targetValue`: The current value of the property in the target object.
7
+ * - `sourceValue`: The value of the property in the source object.
8
+ * - `key`: The key of the property being merged.
9
+ * - `target`: The target object.
10
+ * - `source`: The source object.
11
+ *
12
+ * The `merge` function should return the value to be set in the target object. If it returns `undefined`, a default deep merge will be applied for arrays and objects:
13
+ *
14
+ * - If a property in the source object is an array or an object and the corresponding property in the target object is also an array or object, they will be merged.
15
+ * - If a property in the source object is undefined, it will not overwrite a defined property in the target object.
16
+ *
17
+ * Note that this function mutates the target object.
18
+ *
19
+ * @param {T} target - The target object into which the source object properties will be merged. This object is modified in place.
20
+ * @param {S} source - The source object whose properties will be merged into the target object.
21
+ * @param {(targetValue: any, sourceValue: any, key: string, target: T, source: S) => any} merge - A custom merge function that defines how properties should be combined. It receives the following arguments:
22
+ * - `targetValue`: The current value of the property in the target object.
23
+ * - `sourceValue`: The value of the property in the source object.
24
+ * - `key`: The key of the property being merged.
25
+ * - `target`: The target object.
26
+ * - `source`: The source object.
27
+ *
28
+ * @returns {T & S} The updated target object with properties from the source object merged in.
29
+ *
30
+ * @template T - Type of the target object.
31
+ * @template S - Type of the source object.
32
+ *
33
+ * @example
34
+ * const target = { a: 1, b: 2 };
35
+ * const source = { b: 3, c: 4 };
36
+ *
37
+ * mergeWith(target, source, (targetValue, sourceValue) => {
38
+ * if (typeof targetValue === 'number' && typeof sourceValue === 'number') {
39
+ * return targetValue + sourceValue;
40
+ * }
41
+ * });
42
+ * // Returns { a: 1, b: 5, c: 4 }
43
+ * @example
44
+ * const target = { a: [1], b: [2] };
45
+ * const source = { a: [3], b: [4] };
46
+ *
47
+ * const result = mergeWith(target, source, (objValue, srcValue) => {
48
+ * if (Array.isArray(objValue)) {
49
+ * return objValue.concat(srcValue);
50
+ * }
51
+ * });
52
+ *
53
+ * expect(result).toEqual({ a: [1, 3], b: [2, 4] });
54
+ */
55
+ declare function mergeWith<T, S>(target: T, source: S, merge: (targetValue: any, sourceValue: any, key: string, target: T, source: S) => any): T & S;
56
+
57
+ export { mergeWith };
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Merges the properties of the source object into the target object.
3
+ *
4
+ * You can provide a custom `merge` function to control how properties are merged. The `merge` function is called for each property that is being merged and receives the following arguments:
5
+ *
6
+ * - `targetValue`: The current value of the property in the target object.
7
+ * - `sourceValue`: The value of the property in the source object.
8
+ * - `key`: The key of the property being merged.
9
+ * - `target`: The target object.
10
+ * - `source`: The source object.
11
+ *
12
+ * The `merge` function should return the value to be set in the target object. If it returns `undefined`, a default deep merge will be applied for arrays and objects:
13
+ *
14
+ * - If a property in the source object is an array or an object and the corresponding property in the target object is also an array or object, they will be merged.
15
+ * - If a property in the source object is undefined, it will not overwrite a defined property in the target object.
16
+ *
17
+ * Note that this function mutates the target object.
18
+ *
19
+ * @param {T} target - The target object into which the source object properties will be merged. This object is modified in place.
20
+ * @param {S} source - The source object whose properties will be merged into the target object.
21
+ * @param {(targetValue: any, sourceValue: any, key: string, target: T, source: S) => any} merge - A custom merge function that defines how properties should be combined. It receives the following arguments:
22
+ * - `targetValue`: The current value of the property in the target object.
23
+ * - `sourceValue`: The value of the property in the source object.
24
+ * - `key`: The key of the property being merged.
25
+ * - `target`: The target object.
26
+ * - `source`: The source object.
27
+ *
28
+ * @returns {T & S} The updated target object with properties from the source object merged in.
29
+ *
30
+ * @template T - Type of the target object.
31
+ * @template S - Type of the source object.
32
+ *
33
+ * @example
34
+ * const target = { a: 1, b: 2 };
35
+ * const source = { b: 3, c: 4 };
36
+ *
37
+ * mergeWith(target, source, (targetValue, sourceValue) => {
38
+ * if (typeof targetValue === 'number' && typeof sourceValue === 'number') {
39
+ * return targetValue + sourceValue;
40
+ * }
41
+ * });
42
+ * // Returns { a: 1, b: 5, c: 4 }
43
+ * @example
44
+ * const target = { a: [1], b: [2] };
45
+ * const source = { a: [3], b: [4] };
46
+ *
47
+ * const result = mergeWith(target, source, (objValue, srcValue) => {
48
+ * if (Array.isArray(objValue)) {
49
+ * return objValue.concat(srcValue);
50
+ * }
51
+ * });
52
+ *
53
+ * expect(result).toEqual({ a: [1, 3], b: [2, 4] });
54
+ */
55
+ declare function mergeWith<T, S>(target: T, source: S, merge: (targetValue: any, sourceValue: any, key: string, target: T, source: S) => any): T & S;
56
+
57
+ export { mergeWith };
@@ -0,0 +1,26 @@
1
+ import { isObjectLike } from '../compat/predicate/isObjectLike.mjs';
2
+
3
+ function mergeWith(target, source, merge) {
4
+ const sourceKeys = Object.keys(source);
5
+ for (let i = 0; i < sourceKeys.length; i++) {
6
+ const key = sourceKeys[i];
7
+ const sourceValue = source[key];
8
+ const targetValue = target[key];
9
+ const merged = merge(targetValue, sourceValue, key, target, source);
10
+ if (merged != null) {
11
+ target[key] = merged;
12
+ }
13
+ else if (Array.isArray(sourceValue)) {
14
+ target[key] = mergeWith(targetValue ?? [], sourceValue, merge);
15
+ }
16
+ else if (isObjectLike(targetValue) && isObjectLike(sourceValue)) {
17
+ target[key] = mergeWith(targetValue ?? {}, sourceValue, merge);
18
+ }
19
+ else if (targetValue === undefined || sourceValue !== undefined) {
20
+ target[key] = sourceValue;
21
+ }
22
+ }
23
+ return target;
24
+ }
25
+
26
+ export { mergeWith };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "es-toolkit",
3
3
  "description": "A state-of-the-art, high-performance JavaScript utility library with a small bundle size and strong type annotations.",
4
- "version": "1.14.0-dev.409+bb94b88e",
4
+ "version": "1.14.0-dev.410+cc3a4674",
5
5
  "homepage": "https://es-toolkit.slash.page",
6
6
  "bugs": "https://github.com/toss/es-toolkit/issues",
7
7
  "repository": {