Skip to content

Commit

Permalink
feat: add deepMerge utility
Browse files Browse the repository at this point in the history
  • Loading branch information
nattallius committed Jul 22, 2021
1 parent 4cff324 commit 11331d8
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 2 deletions.
25 changes: 25 additions & 0 deletions src/modules/esl-utils/misc/object.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,28 @@ export const get = (data: any, path: string, defaultValue?: any): any => {
}, data);
return typeof result === 'undefined' ? defaultValue : result;
};

/**
* Performs a deep merge of objects and returns new object.
* Does not modify objects (immutable)
* @param objects to merge
* @returns new object with merged key/values
*/
export function deepMerge(...objects: any[]): any {
return objects.reduce((res: any, obj: any) => {
isObject(obj) && Object.keys(obj).forEach((key) => {
const resultVal = res[key];
const objectVal = obj[key];

if (Array.isArray(objectVal)) {
res[key] = objectVal.slice();
} else if (isObject(resultVal) && isObject(objectVal)) {
res[key] = deepMerge(resultVal, objectVal);
} else {
res[key] = objectVal;
}
});

return res;
}, {});
}
17 changes: 15 additions & 2 deletions src/modules/esl-utils/misc/test/object.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {defined, deepCompare, getPropertyDescriptor, get, set, copyDefinedKeys, copy, omit} from '../object';
import {defined, deepCompare, getPropertyDescriptor, get, set, copyDefinedKeys, copy, omit, deepMerge} from '../object';

describe('misc/object', () => {
describe('deepCompare', () => {
Expand Down Expand Up @@ -144,7 +144,6 @@ describe('misc/object', () => {
});

describe('omit', () => {
const predicate = (key: string) => !key.startsWith('_');
test.each([
[undefined, ['prop'], {}],
[null, ['prop'], {}],
Expand Down Expand Up @@ -189,4 +188,18 @@ describe('misc/object', () => {
expect(targ).toEqual(expVal)
});
});

describe('deepMerge', () => {
test.each([
[{}, {}, {}],
[{a: 1, b: 1}, {a: 2, c: 2}, {a: 2, b: 1, c: 2}],
[{a: {a: 1, b: 1}, b: 1}, {a: {a: 3, c: 3}}, {a: {a: 3, b: 1, c: 3}, b: 1}],
[{a: 1}, {b: 2}, {c: 3}, {a: 1, b: 2, c: 3}],
[{a: 'value', b: 'value'}, {a: null, b: ''}, {a: null, b: ''}],
[{a: [1, 2, {a: 1, b: 1}]}, {a: [3, 4, {a: 2, b: 2}]}, {a: [3, 4, {a: 2, b: 2}]}]
])('get key "%s" from %p', (...args: any[]) => {
const result = args.pop();
expect(deepMerge(...args)).toEqual(result);
});
});
});

0 comments on commit 11331d8

Please sign in to comment.