super-utils-plus
Version:
A superior alternative to Lodash with improved performance, TypeScript support, and developer experience
89 lines (88 loc) • 3.02 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.merge = merge;
const is_1 = require("../utils/is");
/**
* Recursively merges own and inherited enumerable string keyed properties of source
* objects into the destination object. Source properties that resolve to undefined
* are skipped if a destination value exists. Array and plain object properties are
* merged recursively. Other objects and value types are overridden by assignment.
*
* @param object - The destination object
* @param sources - The source objects
* @returns The destination object
*
* @example
* ```ts
* const object = {
* 'a': [{ 'b': 2 }, { 'd': 4 }]
* };
*
* const other = {
* 'a': [{ 'c': 3 }, { 'e': 5 }]
* };
*
* merge(object, other);
* // => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] }
* ```
*/
function merge(object, ...sources) {
if (!sources.length) {
return object;
}
const source = sources.shift();
if ((0, is_1.isObject)(object) && (0, is_1.isObject)(source)) {
for (const key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
const srcValue = source[key];
const objValue = object[key];
// Skip undefined values
if (srcValue === undefined) {
continue;
}
// Recursively merge arrays
if ((0, is_1.isArray)(srcValue) && (0, is_1.isArray)(objValue)) {
object[key] = mergeArrays(objValue, srcValue);
}
// Recursively merge objects
else if ((0, is_1.isObject)(srcValue) && (0, is_1.isObject)(objValue)) {
object[key] = merge(objValue, srcValue);
}
// Otherwise simply assign
else {
object[key] = srcValue;
}
}
}
}
// Continue merging with the next source
return sources.length ? merge(object, ...sources) : object;
}
/**
* Merges two arrays by index, recursively merging objects at the same position.
*/
function mergeArrays(arr1, arr2) {
const result = [...arr1];
for (let i = 0; i < arr2.length; i++) {
const item2 = arr2[i];
// If we're beyond the bounds of arr1, simply append
if (i >= arr1.length) {
result.push(item2);
continue;
}
const item1 = result[i];
// If both items are objects, recursively merge them
if ((0, is_1.isObject)(item1) && (0, is_1.isObject)(item2)) {
result[i] = merge(item1, item2);
}
// If both items are arrays, recursively merge them
else if ((0, is_1.isArray)(item1) && (0, is_1.isArray)(item2)) {
result[i] = mergeArrays(item1, item2);
}
// Otherwise use the value from arr2
else if (item2 !== undefined) {
result[i] = item2;
}
}
return result;
}