CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-deepmerge

A library for deep (recursive) merging of Javascript objects

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

deepmerge

deepmerge is a library for deep (recursive) merging of JavaScript objects. It creates new objects without modifying the original objects, providing a safe way to combine object data with customizable merge behavior for arrays and special object types.

Package Information

  • Package Name: deepmerge
  • Package Type: npm
  • Language: JavaScript (with TypeScript definitions)
  • Installation: npm install deepmerge
  • Main Entry: dist/cjs.js (CommonJS)
  • Browser Usage: Available as UMD from unpkg.com

Core Imports

const merge = require('deepmerge');

For TypeScript projects:

import * as merge from 'deepmerge';

Alternative TypeScript import syntax:

import merge = require('deepmerge');

Note: deepmerge is a CommonJS module. The ESM entry point was removed due to a Webpack bug.

Accessing types in TypeScript:

import merge = require('deepmerge');
// Types are accessible via the merge namespace:
const options: merge.Options = { clone: true };
const arrayOptions: merge.ArrayMergeOptions = { /* ... */ };

For browser usage without bundlers:

<script src="https://unpkg.com/deepmerge/dist/umd.js"></script>
<script>
  const result = deepmerge({ a: 1 }, { b: 2 });
</script>

Basic Usage

const merge = require('deepmerge');

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 = merge(x, y);
// Result: {
//   foo: { bar: 3, baz: 4 },
//   array: [
//     { does: 'work', too: [ 1, 2, 3 ] },
//     { does: 'work', too: [ 4, 5, 6 ] },
//     { really: 'yes' }
//   ],
//   quux: 5
// }

Capabilities

Deep Object Merging

Merge two objects deeply, returning a new merged object with elements from both inputs.

function deepmerge<T>(x: Partial<T>, y: Partial<T>, options?: Options): T;
function deepmerge<T1, T2>(x: Partial<T1>, y: Partial<T2>, options?: Options): T1 & T2;

Parameters:

  • x - Target object to merge into
  • y - Source object to merge from
  • options - Optional configuration object

Returns: New merged object combining properties from both inputs

Usage Example:

const target = { name: 'John', details: { age: 30 } };
const source = { details: { city: 'NYC' }, active: true };

const result = merge(target, source);
// Result: { name: 'John', details: { age: 30, city: 'NYC' }, active: true }

Multiple Object Merging

Merge any number of objects into a single result object.

export function all(objects: object[], options?: Options): object;
export function all<T>(objects: Partial<T>[], options?: Options): T;

Parameters:

  • objects - Array of objects to merge (must be an array)
  • options - Optional configuration object

Returns: Single merged object containing all properties

Throws: Error if first argument is not an array

Usage Example:

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

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

Configuration Options

Merge Options

Configure merge behavior through the options parameter.

interface Options {
  arrayMerge?: (target: any[], source: any[], options?: ArrayMergeOptions) => any[];
  clone?: boolean;
  customMerge?: (key: string, options?: Options) => ((x: any, y: any) => any) | undefined;
  isMergeableObject?: (value: object) => boolean;
}

interface ArrayMergeOptions {
  isMergeableObject(value: object): boolean;
  cloneUnlessOtherwiseSpecified(value: object, options?: Options): object;
}

Array Merge Customization

By default, arrays are merged by concatenation. Customize this behavior with the arrayMerge option.

Overwrite Arrays Example:

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

const result = merge(
  [1, 2, 3],
  [3, 2, 1],
  { arrayMerge: overwriteMerge }
);
// Result: [3, 2, 1]

Combine Arrays Example:

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;
};

const result = merge(
  [{ a: true }],
  [{ b: true }, 'ah yup'],
  { arrayMerge: combineMerge }
);
// Result: [{ a: true, b: true }, 'ah yup']

Object Mergeability Control

Control which objects are considered mergeable with the isMergeableObject option.

Usage Example:

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

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

const target = { someProperty: { cool: 'oh for sure' } };
const source = { someProperty: new SuperSpecial() };

// Default behavior - merges properties
const defaultOutput = merge(target, source);
// defaultOutput.someProperty instanceof SuperSpecial === false

// Custom behavior - preserves special objects
const customOutput = merge(target, source, {
  isMergeableObject: isPlainObject
});
// customOutput.someProperty instanceof SuperSpecial === true

Property-Specific Merging

Customize merge behavior for specific properties using the customMerge option.

Usage Example:

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;
    }
    // Return undefined to use default merge behavior
  }
};

const result = merge(alex, tony, options);
// Result: {
//   name: 'Alex and Tony',
//   pets: ['Cat', 'Parrot', 'Dog']
// }

Clone Control

The clone option controls whether child objects are cloned (default: true).

Usage Example:

const target = { nested: { value: 1 } };
const source = { nested: { value: 2 } };

// With cloning (default)
const cloned = merge(target, source);
cloned.nested !== target.nested; // true

// Without cloning (deprecated)
const notCloned = merge(target, source, { clone: false });

Important Behaviors

Immutability

deepmerge creates new objects and does not modify the original inputs.

const original = { a: 1 };
const addition = { b: 2 };
const result = merge(original, addition);

// original is unchanged
console.log(original); // { a: 1 }
console.log(result);   // { a: 1, b: 2 }

Prototype Pollution Protection

deepmerge includes protection against prototype poisoning attacks by checking property safety.

Type Precedence

When merging values of different types, the source value takes precedence:

const result = merge({ key: [1, 2] }, { key: 'string' });
// Result: { key: 'string' }

Symbol Property Support

Enumerable symbol properties are included in the merge process alongside regular string keys.

Install with Tessl CLI

npx tessl i tessl/npm-deepmerge
Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/deepmerge@4.3.x
Publish Source
CLI
Badge
tessl/npm-deepmerge badge