How to Merge Objects in TypeScript
In TypeScript, merging objects is a common operation that can be achieved in various ways, depending on the desired outcome and the nuances of the merge. This guide will walk you through several methods of merging objects in TypeScript, highlighting their strengths and differences.
Object Spread Operator
The spread operator (...
) is a handy ES6 feature that allows for the creation of shallow copies of objects and arrays. When it comes to merging objects, you can use the spread operator to combine two or more objects into one.
const obj1 = { a: 1, b: 2 }; const obj2 = { b: 3, c: 4 }; const merged = { ...obj1, ...obj2 }; console.log(merged); // { a: 1, b: 3, c: 4 }
Note: If properties from obj1
and obj2
have the same key, the latter object's value will override the former's.
Object.assign()
Object.assign()
is a method that was introduced in ES6 to copy values of all enumerable properties from one or more source objects to a target object.
const obj1 = { a: 1, b: 2 }; const obj2 = { b: 3, c: 4 }; const merged = Object.assign({}, obj1, obj2); console.log(merged); // { a: 1, b: 3, c: 4 }
Note: Like the spread operator, properties from later sources will overwrite those of earlier ones.
Deep Merging
The methods above only perform shallow merges. If nested objects are present, they'll be overwritten rather than merged. For a deep merge, a custom function is often required.
function deepMerge(obj1: any, obj2: any): any { const output = Object.assign({}, obj1); for (const key in obj2) { if (Object.prototype.hasOwnProperty.call(obj2, key)) { if (typeof obj2[key] === 'object' && obj2[key] !== null && obj1[key]) { output[key] = deepMerge(obj1[key], obj2[key]); } else { output[key] = obj2[key]; } } } return output; } const obj1 = { a: { x: 10, y: 20 }, b: 2 }; const obj2 = { a: { y: 30, z: 40 }, c: 4 }; const merged = deepMerge(obj1, obj2); console.log(merged); // { a: { x: 10, y: 30, z: 40 }, b: 2, c: 4 }
Type Intersections for Merging Object Types
In TypeScript, if you're looking to merge types of objects (rather than the objects themselves), you can use type intersections.
type A = { a: number; b: number; }; type B = { b: string; c: string; }; type Merged = A & B; // This will result in: // type Merged = { // a: number; // b: number & string; // <-- This might not be what you want! // c: string; // }
While type intersections can create merged types, be cautious of overlapping property names as they may result in never types or other undesirable unions.
Utility Types for Merging
TypeScript also provides utility types that can assist with merging. One of the commonly used utility types is Partial<T>
, which makes all properties of type T
optional.
type A = { a: number; b: number; }; function mergeWithDefault(obj: Partial<A>): A { return { a: 0, b: 0, ...obj }; } const merged = mergeWithDefault({ a: 1 }); // { a: 1, b: 0 }
In this example, the mergeWithDefault
function can accept a partial version of A
and merge it with the default values.
By leveraging TypeScript and ES6+ features, you can efficiently merge objects in a variety of ways. Always remember to choose the merging strategy that aligns best with your specific requirements.
Invite only
We're building the next generation of data visualization.
How to turn webpages into editable canvases with a JavaScript bookmarklet
Kris Lachance
How to fix the "not all code paths return a value" issue in TypeScript
Kris Lachance
Working with WebSockets in Node.js using TypeScript
Kris Lachance
Type Annotations Can Only Be Used in TypeScript Files
Kris Lachance
Guide to TypeScript Recursive Type
Kris Lachance
How to Configure Knex.js with TypeScript
Kris Lachance