Strongly-typed deep and recursive object merging with support for all value types.
pnpm add object-deep-merge
yarn add object-deep-merge
npm install object-deep-merge
import { merge } from "object-deep-merge";
const merged = merge({ foo: false }, { bar: true });
console.log({ merged });
Output
{
"merged": {
"foo": false,
"bar": true
}
}
The merge
function accepts two optional type generics. TData
and TResult
.
function merge<TData extends MergeableObject = MergeableObject, TResult extends MergeableObject = TData>(
source: TData,
target: TData,
...targets: Array<TData>
): TResult;
Important
The Merge
and MergeDeep
types from type-fest
are shipped from this library as a convenience. It is not unreasonable to use those types directly instead.
Without explicitly passing in types the function will infer the shape of the object(s) passed in.
- Passing in
TData
will validate the shape of the objects passed in. - Passing in
TResult
will override the output type. While this should be used sparingly, it provides a convenient approach for correctly typing partial types into complete types.
type Data = {
name: string;
description: string;
};
const base: Data = { name: "object-deep-merge", description: "merge objects" };
const overrides: Partial<Data> = { description: "merge objects, deeply" };
const merged = merge(base, overrides);
// Type is inferred so the signature becomes:
// function merge<Partial<Data>, Partial<Data>>(source: Partial<Data>, target: Partial<Data>, ...targets: Partial<Data>[]): Partial<Data>
// TData = Partial<Data>
// TResult = Data
console.log({ merged });
Output
{
"merged": {
"name": "object-deep-merge",
"description": "merge objects, deeply"
}
}
Note
Passing in TData will validate the shape of the objects passed in.
type Data = {
name: string;
description: string;
};
const base: Data = { name: "object-deep-merge", description: "merge objects" };
const overrides: Partial<Data> = { description: "merge objects, deeply" };
const merged: Partial<Data> = merge<Partial<Data>>(base, overrides);
// TData = Partial<Data>
// TResult = Data
console.log({ merged });
Output
{
"merged": {
"name": "object-deep-merge",
"description": "merge objects, deeply"
}
}
Note
Passing in TResult
will override the output type. While this should be used sparingly, it provides a convenient approach for correctly typing partial types into complete types.
type Data = {
name: string;
description: string;
};
const base: Data = { name: "object-deep-merge", description: "merge objects" };
const overrides: Partial<Data> = { description: "merge objects, deeply" };
const merged: Data = merge<Partial<Data>, Data>(base, overrides);
// TData = Partial<Data>
// TResult = Data
console.log({ merged });
Output
{
"merged": {
"name": "object-deep-merge",
"description": "merge objects, deeply"
}
}