UNPKG

super-utils-plus

Version:

A superior alternative to Lodash with improved performance, TypeScript support, and developer experience

89 lines (88 loc) 3.02 kB
"use strict"; 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; }