Skip to content

v8.0.0

Choose a tag to compare

@github-actions github-actions released this 16 Aug 03:49
· 3 commits to main since this release
Immutable release. Only release title and notes can be modified.

8.0.0 (2026-08-16)

Breaking Changes

  • Deep Map value merging. Map values are now deep-merged by default, matching how records are handled. Nested Maps and plain objects inside a Map are merged recursively rather than the source Map simply replacing the target. The old behaviour can be recreated with deepmergeCustom({ mergeMaps: false }).
  • DeepMergeMetaMetaData renamed to DeepMergeMergeInfo. A deprecated alias for the old name is still exported for backwards compatibility, but it will be removed in a future major version. The rename better reflects the structure's expanded role, including hierarchy tracking, in custom merging and the metadata passed to custom merge functions. The MetaDataUpdater callback's metaMeta parameter is now mergeInfo, and the MM generic shorthand is now MI.
  • DeepMergeIntoFunctionUtils renamed to DeepMergeIntoUtils. No alias is kept for the old name.
  • deepmergeInto no longer leak-mutates the input objects. Previously deepmergeInto would mutate the first object's nested containers (arrays, Maps, Sets, and objects) in place, potentially corrupting the input. It is now fixed.

Features

  • Circular reference support. deepmergeCustom and deepmergeIntoCustom now handle circular references, configurable via a new maxDepth option and a new mergeCircularReferences merge-function option. The merge metadata also now tracks the merge hierarchy.
  • New fast entrypoints. deepmergeFastUnsafe and deepmergeIntoFastUnsafe are drop-in replacements for deepmerge and deepmergeInto with prototype-pollution interception, circular-reference handling, and metadata tracking removed for maximum throughput. They should only be used with trusted data. Each ships with a *Custom constructor (deepmergeFastUnsafeCustom and deepmergeIntoFastUnsafeCustom) for customisation.

Bug Fixes

  • deepmergeInto no longer leak-mutates the input objects. (As described in Breaking Changes.)

Performance

  • Much faster type checking. The following numbers are the type-checking cost, comparing this release against v7.1.6 (measured with TypeScript 5.9.3):

    Scenario Types Instantiations Total time
    wide 256k -> 26k (-90%) 6.5M -> 83k (-98.7%) 10.5s -> 0.94s (-91%)
    deep 64k -> 26k (-60%) 438k -> 67k (-85%) 1.82s -> 0.87s (-52%)
    optional 45k -> 27k (-40%) 172k -> 78k (-55%) 1.39s -> 0.89s (-36%)
    unions 40k -> 26k (-36%) 118k -> 69k (-42%) 1.26s -> 0.92s (-27%)
    collections 37k -> 26k (-29%) 95k -> 69k (-28%) 1.22s -> 1.06s (-13%)
    custom 38k -> 26k (-31%) 100k -> 69k (-31%) 1.22s -> 1.02s (-16%)
    into 35k -> 25k (-27%) 76k -> 64k (-15%) 1.20s -> 0.87s (-28%)
  • Runtime performance. Compared to v7.1.6, deepmerge-ts v8.0.0 is roughly 40% faster when merging two objects and ~5-10% faster on multi-object merges, while deepmergeInto performs about the same (its leak-mutation fix adds a little clone work). Memory use is markedly lower as well: on the largest benchmark dataset, v7.1.6 runs into Node's default heap limit, whereas the same workload completes with a peak of roughly half a gigabyte.

  • Compared to other merge libraries we benchmark against.

    • Deep, nested data. defu@6.1.7 is the fastest. When merging many objects, deepmerge-ts@8.0.0 is within ~1.5x and merge-anything@6.0.6 close behind; on simple two-object merges defu pulls further ahead (~1.1-2x).
    • Medium data. When merging many objects at once, deepmerge-ts edges out defu (~1.5x) and is ~2.5x faster than merge-anything.
    • Wide, shallow data. When merging many objects at once, deepmerge-ts is the fastest, roughly 25-35x faster than both defu and merge-anything.
    • The other libraries (ts-deepmerge@8.0.0, mergician@2.0.2, @fastify/deepmerge@3.2.1, deepmerge@4.3.1) fall anywhere from ~100x to ~17,000x behind, largely because they deep-clone the entire input, whereas deepmerge-ts shares references to untouched subtrees.
    • Set and Map values. Only deepmerge-ts merges them deeply, by unioning Set elements and merging Map entries (including their values), while the other libraries simply let one of the values win.

Security


For a line-by-line breakdown of every commit, see the CHANGELOG.