All files / object merge.ts

100% Statements 22/22
90% Branches 9/10
100% Functions 3/3
100% Lines 21/21

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55                            13x 1x     12x 12x 6x   6x 6x 9x 2x 1x 2x     7x       6x     1x 1x   1x 1x 1x 1x 1x       1x            
import { isPlainObject } from '../is'
 
/**
 * The method is like Object.assign except that
 * it recursively merges own and inherited enumerable string keyed properties of source objects
 * into the destination object.
 *
 * @param target the destination object
 * @param sources the source objects
 * @returns object
 *
 * {@link https://lodash.com/docs#merge}
 */
export function merge<T extends object>(target: T, ...sources: any[]): T {
  if (!isPlainObject(target)) {
    return target
  }
 
  const validSources = sources.filter(source => isPlainObject(source))
  if (!validSources.length)
    return target
 
  const source = validSources.shift()
  for (const key in source) {
    if (isPlainObject(source[key])) {
      if (!Object.prototype.hasOwnProperty.call(target, key))
        Object.assign(target, { [key]: {} })
      merge((target as Record<string, any>)[key], source[key])
    }
    else {
      Object.assign(target, { [key]: source[key] })
    }
  }
 
  return merge(target, ...validSources)
}
 
Eif (import.meta.vitest) {
  const { test, expect } = import.meta.vitest
 
  test('merge', () => {
    expect(merge([], { name: 'merge' })).toEqual([])
    expect(merge({}, 1, '2', { name: 'merge' })).toEqual({ name: 'merge' })
    expect(merge({ name: 'Merge' }, { name: 'merge' })).toEqual({ name: 'merge' })
    expect(merge(
      { name: 'merge' },
      { pkg: { name: 'usexx', license: 'MIT' } },
    )).toEqual({ name: 'merge', pkg: { name: 'usexx', license: 'MIT' } })
    expect(merge(
      { name: 'Merge', pkg: { name: 'use', keyword: 'toolkit' } },
      { name: 'merge', pkg: { name: 'usexx', license: 'MIT' } },
    )).toEqual({ name: 'merge', pkg: { name: 'usexx', keyword: 'toolkit', license: 'MIT' } })
  })
}