File tree Expand file tree Collapse file tree 3 files changed +29
-2
lines changed Expand file tree Collapse file tree 3 files changed +29
-2
lines changed Original file line number Diff line number Diff line change @@ -370,6 +370,14 @@ describe('merge', () => {
370370 expect ( actual ) . toEqual ( { a : [ 'x' , 'y' , 'z' ] } ) ;
371371 } ) ;
372372
373+ it ( 'should not preserve object properties when nested object is replaced by array' , ( ) => {
374+ const actual = merge ( { x : { a : 2 } } , { x : [ '1' ] } ) ;
375+
376+ expect ( actual . x ) . toEqual ( [ '1' ] ) ;
377+ expect ( Object . keys ( actual . x ) ) . toEqual ( [ '0' ] ) ;
378+ expect ( ( actual . x as any ) . a ) . toBeUndefined ( ) ;
379+ } ) ;
380+
373381 it ( 'should match the type of lodash' , ( ) => {
374382 expectTypeOf ( merge ) . toEqualTypeOf < typeof mergeLodash > ( ) ;
375383 } ) ;
Original file line number Diff line number Diff line change @@ -228,4 +228,12 @@ describe('mergeWith', () => {
228228 result = mergeWith ( { a : 1 } , { a : undefined } , noop ) ;
229229 expect ( result . a ) . toBe ( 1 ) ;
230230 } ) ;
231+
232+ it ( 'should not preserve object properties when nested object is replaced by array' , ( ) => {
233+ const actual = mergeWith ( { x : { a : 2 } } , { x : [ '1' ] } , noop ) ;
234+
235+ expect ( actual . x ) . toEqual ( [ '1' ] ) ;
236+ expect ( Object . keys ( actual . x ) ) . toEqual ( [ '0' ] ) ;
237+ expect ( ( actual . x as any ) . a ) . toBeUndefined ( ) ;
238+ } ) ;
231239} ) ;
Original file line number Diff line number Diff line change @@ -4,6 +4,7 @@ import { clone } from '../../object/clone.ts';
44import { isPrimitive } from '../../predicate/isPrimitive.ts' ;
55import { getSymbols } from '../_internal/getSymbols.ts' ;
66import { isArguments } from '../predicate/isArguments.ts' ;
7+ import { isArrayLikeObject } from '../predicate/isArrayLikeObject.ts' ;
78import { isObjectLike } from '../predicate/isObjectLike.ts' ;
89import { isPlainObject } from '../predicate/isPlainObject.ts' ;
910import { isTypedArray } from '../predicate/isTypedArray.ts' ;
@@ -292,15 +293,25 @@ function mergeWithDeep(
292293 }
293294
294295 if ( Array . isArray ( sourceValue ) ) {
295- if ( typeof targetValue === 'object' && targetValue != null ) {
296+ if ( Array . isArray ( targetValue ) ) {
296297 const cloned : any = [ ] ;
298+ // for custom properties on arrays
297299 const targetKeys = Reflect . ownKeys ( targetValue ) ;
298300
299301 for ( let i = 0 ; i < targetKeys . length ; i ++ ) {
300- const targetKey = targetKeys [ i ] ;
302+ const targetKey = targetKeys [ i ] as keyof typeof targetValue ;
301303 cloned [ targetKey ] = targetValue [ targetKey ] ;
302304 }
303305
306+ targetValue = cloned ;
307+ } else if ( isArrayLikeObject ( targetValue ) ) {
308+ // array-like object: only copy numeric indices
309+ const cloned : any = [ ] ;
310+
311+ for ( let i = 0 ; i < targetValue . length ; i ++ ) {
312+ cloned [ i ] = targetValue [ i ] ;
313+ }
314+
304315 targetValue = cloned ;
305316 } else {
306317 targetValue = [ ] ;
You can’t perform that action at this time.
0 commit comments