Skip to content

Commit 5b2b75c

Browse files
committed
feat(deepMergeWithArray): new function
1 parent 7f8b16c commit 5b2b75c

2 files changed

Lines changed: 69 additions & 2 deletions

File tree

‎src/object.test.ts‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import{describe,expect,it}from'vitest'
2-
import{deepMerge,objectMap}from'./object'
2+
import{deepMerge,deepMergeWithArray,objectMap}from'./object'
33

44
it('objectMap',()=>{
55
expect(objectMap({},(...args)=>args)).toEqual({})
@@ -64,3 +64,11 @@ describe('deepMerge', () => {
6464
expect(obj2.polluted).toBeUndefined()
6565
})
6666
})
67+
68+
describe('deepMergeWithArray',()=>{
69+
it('should merge array values',()=>{
70+
constobj1={a: ['A','B']}
71+
constobj2={a: ['C'],b: ['D']}
72+
expect(deepMergeWithArray({},obj1,obj2)).toEqual({a: ['A','B','C'],b: ['D']})
73+
})
74+
})

‎src/object.ts‎

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,10 @@ export function objectEntries<T extends object>(obj: T) {
6868
}
6969

7070
/**
71-
* Deep merge :P
71+
* Deep merge
72+
*
73+
* The first argument is the target object, the rest are the sources.
74+
* The target object will be mutated and returned.
7275
*
7376
* @category Object
7477
*/
@@ -105,6 +108,62 @@ export function deepMerge<T extends object = object, S extends object = T>(targe
105108
returndeepMerge(target, ...sources)
106109
}
107110

111+
/**
112+
* Deep merge
113+
*
114+
* Differs from `deepMerge` in that it merges arrays instead of overriding them.
115+
*
116+
* The first argument is the target object, the rest are the sources.
117+
* The target object will be mutated and returned.
118+
*
119+
* @category Object
120+
*/
121+
exportfunctiondeepMergeWithArray<Textendsobject=object,Sextendsobject=T>(target: T, ...sources: S[]): DeepMerge<T,S>{
122+
if(!sources.length)
123+
returntargetasany
124+
125+
constsource=sources.shift()
126+
if(source===undefined)
127+
returntargetasany
128+
129+
if(Array.isArray(target)&&Array.isArray(source))
130+
target.push(...source)
131+
132+
if(isMergableObject(target)&&isMergableObject(source)){
133+
objectKeys(source).forEach((key)=>{
134+
if(key==='__proto__'||key==='constructor'||key==='prototype')
135+
return
136+
137+
// @ts-expect-error
138+
if(Array.isArray(source[key])){
139+
// @ts-expect-error
140+
if(!target[key])
141+
// @ts-expect-error
142+
target[key]=[]
143+
144+
// @ts-expect-error
145+
deepMergeWithArray(target[key],source[key])
146+
}
147+
// @ts-expect-error
148+
elseif(isMergableObject(source[key])){
149+
// @ts-expect-error
150+
if(!target[key])
151+
// @ts-expect-error
152+
target[key]={}
153+
154+
// @ts-expect-error
155+
deepMergeWithArray(target[key],source[key])
156+
}
157+
else{
158+
// @ts-expect-error
159+
target[key]=source[key]
160+
}
161+
})
162+
}
163+
164+
returndeepMergeWithArray(target, ...sources)
165+
}
166+
108167
functionisMergableObject(item: any): item is Object{
109168
returnisObject(item)&&!Array.isArray(item)
110169
}

0 commit comments

Comments
 (0)