Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

deepmerge

TehShrike161.2mMIT4.3.1TypeScript support: included

A library for deep (recursive) merging of Javascript objects

merge, deep, extend, copy, clone, recursive

readme

deepmerge

Merges the enumerable properties of two or more objects deeply.

UMD bundle is 723B minified+gzipped

Getting Started

Example Usage

const x = {
    foo: { bar: 3 },
    array: [{
        does: 'work',
        too: [ 1, 2, 3 ]
    }]
}

const y = {
    foo: { baz: 4 },
    quux: 5,
    array: [{
        does: 'work',
        too: [ 4, 5, 6 ]
    }, {
        really: 'yes'
    }]
}

const output = {
    foo: {
        bar: 3,
        baz: 4
    },
    array: [{
        does: 'work',
        too: [ 1, 2, 3 ]
    }, {
        does: 'work',
        too: [ 4, 5, 6 ]
    }, {
        really: 'yes'
    }],
    quux: 5
}

merge(x, y) // => output

Installation

With npm do:

npm install deepmerge

deepmerge can be used directly in the browser without the use of package managers/bundlers as well: UMD version from unpkg.com.

Include

deepmerge exposes a CommonJS entry point:

const merge = require('deepmerge')

The ESM entry point was dropped due to a Webpack bug.

API

merge(x, y, [options])

Merge two objects x and y deeply, returning a new merged object with the elements from both x and y.

If an element at the same key is present for both x and y, the value from y will appear in the result.

Merging creates a new object, so that neither x or y is modified.

Note: By default, arrays are merged by concatenating them.

merge.all(arrayOfObjects, [options])

Merges any number of objects into a single result object.

const foobar = { foo: { bar: 3 } }
const foobaz = { foo: { baz: 4 } }
const bar = { bar: 'yay!' }

merge.all([ foobar, foobaz, bar ]) // => { foo: { bar: 3, baz: 4 }, bar: 'yay!' }

Options

arrayMerge

There are multiple ways to merge two arrays, below are a few examples but you can also create your own custom function.

Your arrayMerge function will be called with three arguments: a target array, the source array, and an options object with these properties:

  • isMergeableObject(value)
  • cloneUnlessOtherwiseSpecified(value, options)

arrayMerge example: overwrite target array

Overwrites the existing array values completely rather than concatenating them:

const overwriteMerge = (destinationArray, sourceArray, options) => sourceArray

merge(
    [1, 2, 3],
    [3, 2, 1],
    { arrayMerge: overwriteMerge }
) // => [3, 2, 1]

arrayMerge example: combine arrays

Combines objects at the same index in the two arrays.

This was the default array merging algorithm pre-version-2.0.0.

const combineMerge = (target, source, options) => {
    const destination = target.slice()

    source.forEach((item, index) => {
        if (typeof destination[index] === 'undefined') {
            destination[index] = options.cloneUnlessOtherwiseSpecified(item, options)
        } else if (options.isMergeableObject(item)) {
            destination[index] = merge(target[index], item, options)
        } else if (target.indexOf(item) === -1) {
            destination.push(item)
        }
    })
    return destination
}

merge(
    [{ a: true }],
    [{ b: true }, 'ah yup'],
    { arrayMerge: combineMerge }
) // => [{ a: true, b: true }, 'ah yup']

isMergeableObject

By default, deepmerge clones every property from almost every kind of object.

You may not want this, if your objects are of special types, and you want to copy the whole object instead of just copying its properties.

You can accomplish this by passing in a function for the isMergeableObject option.

If you only want to clone properties of plain objects, and ignore all "special" kinds of instantiated objects, you probably want to drop in is-plain-object.

const { isPlainObject } = require('is-plain-object')

function SuperSpecial() {
    this.special = 'oh yeah man totally'
}

const instantiatedSpecialObject = new SuperSpecial()

const target = {
    someProperty: {
        cool: 'oh for sure'
    }
}

const source = {
    someProperty: instantiatedSpecialObject
}

const defaultOutput = merge(target, source)

defaultOutput.someProperty.cool // => 'oh for sure'
defaultOutput.someProperty.special // => 'oh yeah man totally'
defaultOutput.someProperty instanceof SuperSpecial // => false

const customMergeOutput = merge(target, source, {
    isMergeableObject: isPlainObject
})

customMergeOutput.someProperty.cool // => undefined
customMergeOutput.someProperty.special // => 'oh yeah man totally'
customMergeOutput.someProperty instanceof SuperSpecial // => true

customMerge

Specifies a function which can be used to override the default merge behavior for a property, based on the property name.

The customMerge function will be passed the key for each property, and should return the function which should be used to merge the values for that property.

It may also return undefined, in which case the default merge behaviour will be used.

const alex = {
    name: {
        first: 'Alex',
        last: 'Alexson'
    },
    pets: ['Cat', 'Parrot']
}

const tony = {
    name: {
        first: 'Tony',
        last: 'Tonison'
    },
    pets: ['Dog']
}

const mergeNames = (nameA, nameB) => `${nameA.first} and ${nameB.first}`

const options = {
    customMerge: (key) => {
        if (key === 'name') {
            return mergeNames
        }
    }
}

const result = merge(alex, tony, options)

result.name // => 'Alex and Tony'
result.pets // => ['Cat', 'Parrot', 'Dog']

clone

Deprecated.

Defaults to true.

If clone is false then child objects will be copied directly instead of being cloned. This was the default behavior before version 2.x.

Testing

With npm do:

npm test

License

MIT

changelog

4.3.1

  • Fix type definition for arrayMerge options. #239

4.3.0

  • Avoid thrown errors if the target doesn't have propertyIsEnumerable. #252

4.2.2

  • isMergeableObject is now only called if there are two values that could be merged. a34dd4d2

4.2.1

  • Fix: falsey values can now be merged. #170

4.2.0

  • Properties are now only overwritten if they exist on the target object and are enumerable. #164

Technically this could probably be a patch release since "which properties get overwritten" wasn't documented and accidentally overwriting a built-in function or some function up the property chain would almost certainly be undesirable, but it feels like a gray area, so here we are with a feature version bump.

4.1.2

  • Rolled back #167 since Object.assign breaks ES5 support. 55067352

4.1.1

  • The options argument is no longer mutated #167

4.1.0

  • cloneUnlessOtherwiseSpecified is now exposed to the arrayMerge function #165

4.0.0

  • The main entry point in package.json is now a CommonJS module instead of a UMD module #155

3.3.0

  • Enumerable Symbol properties are now copied #151

3.2.1

  • bumping dev dependency versions to try to shut up bogus security warnings from Github/npm #149

3.2.0

3.1.0

  • typescript typing: make the all function generic #129

3.0.0

  • drop ES module build #123

2.2.1

  • bug: typescript export type was wrong #121

2.2.0

  • feature: added TypeScript typings #119

2.1.1

  • documentation: Rename "methods" to "api", note ESM syntax #103
  • documentation: Fix grammar #107
  • documentation: Restructure headers for clarity + some wording tweaks 108 + 109

2.1.0

  • feature: Support a custom isMergeableObject function #96
  • documentation: note a Webpack bug that some users might need to work around #100

2.0.1

  • documentation: fix the old array merge algorithm in the readme. #84

2.0.0

  • breaking: the array merge algorithm has changed from a complicated thing to target.concat(source).map(element => cloneUnlessOtherwiseSpecified(element, optionsArgument))
  • breaking: The clone option now defaults to true
  • feature: merge.all now accepts an array of any size, even 0 or 1 elements

See pull request 77.

1.5.2

  • fix: no longer attempts to merge React elements #76

1.5.1

  • bower support: officially dropping bower support. If you use bower, please depend on the unpkg distribution. See #63

1.5.0

  • bug fix: merging objects into arrays was allowed, and doesn't make any sense. #65 published as a feature release instead of a patch because it is a decent behavior change.

1.4.4

  • bower support: updated main in bower.json

1.4.3

  • bower support: inline is-mergeable-object in a new CommonJS build, so that people using both bower and CommonJS can bundle the library 0b34e6

1.4.2

  • performance: bump is-mergeable-object dependency version for a slight performance improvement 5906c7

1.4.1

  • documentation: fix unpkg link acc45b

1.4.0

  • api: instead of only exporting a UMD module, expose a UMD module with pkg.main, a CJS module with pkg.browser, and an ES module with pkg.module #62

1.3.2

  • documentation: note the minified/gzipped file sizes 56
  • documentation: make data structures more readable in merge example: pull request 57

1.3.1

  • documentation: clarify and test some array merging documentation: pull request 51

1.3.0

  • feature: merge.all, a merge function that merges any number of objects: pull request 50

1.2.0

  • fix: an error that would be thrown when an array would be merged onto a truthy non-array value: pull request 46
  • feature: the ability to clone: Issue 28, pull requests 44 and 48
  • maintenance: added tests + travis to .npmignore: pull request 47

1.1.1

  • fix an issue where an error was thrown when merging an array onto a non-array: Pull request 46

1.1.0

  • allow consumers to specify their own array merging algorithm: Pull request 37

1.0.3

  • adding bower.json back: Issue 38
  • updating keywords and Github links in package.json bc3898e

1.0.2

  • Updating the readme: dropping bower, testing that the example works: 7102fc

1.0.1

  • null, dates, and regular expressions are now properly merged in arrays: Issue 18, plus commit: ef1c6b

1.0.0

  • Should only be a patch change, because this module is READY. Issue 15
  • Regular expressions are now treated like primitive values when merging: Issue 30
  • Dates are now treated like primitives when merging: Issue 31