How to Merge Two Objects in TypeScript?

Do you want to know how to merge two objects in Typescript? In this Typescript tutorial, I will explain how to merge two objects in Typescript with different examples.

In TypeScript, you can merge two objects by using the spread operator … to combine the properties of both objects into a new one. Alternatively, you can use Object.assign() to achieve the same result. Both methods will create a shallow merge of the objects. For instance, let mergedObject = { …object1, …object2 }; will combine object1 and object2 into mergedObject.

Typescript merge objects

In TypeScript, merging objects is a common operation that combines properties from two or more objects into a single object. The outcome is a new object with properties copied from those source objects.

Here is how to merge objects in Typescript using different methods.

The Object.assign() Method

Object.assign() is a method in Typescript that is used to copy values from one or more source objects to a target object. It performs a shallow merge, copying property values:

const target = {};
const source1 = { a: 1 };
const source2 = { b: 2 };
Object.assign(target, source1, source2);
// target now is { a: 1, b: 2 }

This method only copies enumerable and own properties from a source object to a target object.

Using Spread Syntax for Merging

The spread operator (...) is a concise and convenient way to merge objects in JavaScript and TypeScript. It allows for the creation of a new object by expanding the properties of existing objects into it:

const obj1 = { name: 'Alice', age: 25 };
const obj2 = { job: 'Engineer' };
const mergedObj = { ...obj1, ...obj2 };
// mergedObj is { name: 'Alice', age: 25, job: 'Engineer' }

The spread syntax is especially useful for immutably updating properties of an object without affecting the original objects.

How to Merge Two Objects in TypeScript

Merging two objects in TypeScript can be done in a couple of ways, but the most common methods are using the spread syntax or the Object.assign() method. Below are detailed explanations and examples for both methods.

Using Spread Syntax

The spread syntax (...) allows an iterable such as an array or object to be expanded in places where zero or more arguments (for function calls) or elements (for array literals) are expected, or an object expression to be expanded in places where zero or more key-value pairs (for object literals) are expected.

Here’s an example of merging two objects using the spread syntax:

const objectA = { name: 'Alice', age: 25 };
const objectB = { job: 'Engineer', country: 'Canada' };

const mergedObject = { ...objectA, ...objectB };
console.log(mergedObject);

This will produce:

{ name: 'Alice', age: 25, job: 'Engineer', country: 'Canada' }

In this example, mergedObject will have all the properties of objectA and objectB. If there are any overlapping properties, the property values from the object that appears later in the spread will override the earlier one.

You can see the output in the screenshot below:

typescript how to merge two objects

Using Object.assign()

The Object.assign() method is used to copy all enumerable own properties from one or more source objects to a target object. It will return the modified target object.

Here’s an example of merging two objects using Object.assign():

const objectA = { name: 'Alice', age: 25 };
const objectB = { job: 'Engineer', country: 'Canada' };

const mergedObject = Object.assign({}, objectA, objectB);
console.log(mergedObject);

This will produce the same result as the spread syntax example:

{ name: 'Alice', age: 25, job: 'Engineer', country: 'Canada' }

In this case, we pass an empty object as the first argument to Object.assign(), which will be the target object that gets modified. The subsequent arguments are the source objects whose properties are copied to the target.

Handling Type Safety

When merging objects in TypeScript, you might want to ensure type safety. You can define interfaces or types to describe the shape of the objects you expect to merge.

For example:

interface Person {
  name: string;
  age: number;
}

interface Job {
  job: string;
  country: string;
}

const objectA: Person = { name: 'Alice', age: 25 };
const objectB: Job = { job: 'Engineer', country: 'Canada' };

const mergedObject = { ...objectA, ...objectB };

In this case, mergedObject will be of type Person & Job, which is an intersection type representing objects that have all the properties of Person and Job.

Remember that both the spread syntax and Object.assign() perform shallow merges. This means that if the objects contain nested objects, those nested objects will not be deeply merged but rather replaced or copied over.

TypeScript: Merge All Objects in Array

Merging all objects in an array into a single object is a common task in TypeScript development. One can perform this operation using several methods, but the most straightforward approach is to use the Object.assign() method or the spread operator ....

When using Object.assign(), initialize an empty object and sequentially assign each object in the array to it. The properties from later objects will overwrite those of the earlier ones if they have the same keys.

Example using Object.assign():

const objectArray = [{ a: 1 }, { b: 2 }, { c: 3 }];
const mergedObject = Object.assign({}, ...objectArray);

This results in mergedObject being { a: 1, b: 2, c: 3 }.

Alternatively, the spread operator provides a concise and readable way to merge objects.

Example using spread operator:

const mergedObject = {...objectArray[0], ...objectArray[1], ...objectArray[2]};

This also yields mergedObject as { a: 1, b: 2, c: 3 }.

Be aware that both methods will only do a shallow merge. If objects contain nested objects, the last one in the sequence will overwrite the entire nested object, not just the conflicting keys. Additional strategies, such as deep merging functions, may be required for more complex structures.

In TypeScript, it’s advisable to specify types for better compile-time checks and auto-completion. Defining an interface that describes the merged object can provide these benefits.

For an array with a dynamic size, a reduce function can merge all objects:

const mergeObjectsInArray = (array: Object[]): Object => array.reduce((acc, obj) => ({...acc, ...obj}), {});

Using these methods ensures a robust solution for merging objects in TypeScript.

TypeScript Merge Objects Overwrite

In TypeScript, merging two objects and overwriting properties is a common task. To achieve an object merge where properties from the second object overwrite those of the first, developers often utilize modern JavaScript (ES6) features, which TypeScript adopts and extends.

Using the Spread Operator (...): The spread operator provides a concise syntax for combining properties from multiple objects into a single object. If the same property exists in both objects, the property value from the last spread object takes precedence.

const obj1 = { name: 'Alice', location: 'Wonderland' };
const obj2 = { location: 'Looking Glass', hobby: 'Adventures' };
const mergedObj = { ...obj1, ...obj2 };

In this example, mergedObj would result in:

{ name: 'Alice', location: 'Looking Glass', hobby: 'Adventures' }

With Object.assign(): Alternatively, Object.assign() can be used to merge objects and allow for overwriting of properties. The method copies the values of all enumerable properties from one or more source objects to a target object.

const obj1 = { name: 'Alice', location: 'Wonderland' };
const obj2 = { location: 'Looking Glass', hobby: 'Adventures' };
const mergedObj = Object.assign({}, obj1, obj2);

The properties from obj2 overwrite those in obj1 where there is a conflict, resulting in the same mergedObj as with the spread operator.

Developers should note that both approaches will not deeply merge nested objects — only top-level properties are considered.

TypeScript Merge Object with Partial

When working with TypeScript, developers might need to merge two partial objects into a single one that satisfies a complete interface. Partial objects are essentially incomplete versions of a particular type, where each property is optional.

To achieve this, they can take advantage of TypeScript’s utility type Partial<T>. Here’s a step-by-step process:

  • Step 1: Define a complete interface: interface CompleteObject { prop1: string; prop2: number; prop3: boolean; }
  • Step 2: Create partial instances: let partial1: Partial<CompleteObject> = { prop1: "example" }; let partial2: Partial<CompleteObject> = { prop2: 42 };
  • Step 3: Merge the partials: let mergedObject: CompleteObject = { ...partial1, ...partial2 } as CompleteObject;

Important Considerations:

  • Use the spread operator (...) to combine the objects.
  • An explicit type assertion (as CompleteObject) is necessary if the partials don’t cover all properties.
  • The merged object must include all required properties of the CompleteObject interface.
  • Conflicts between objects resolve by the last-in priority, where the properties in the latter object overwrite those in the former.

This concise method ensures that developers can construct complex objects from simpler parts while maintaining type safety.

TypeScript Merge Object with Default Values

When working with TypeScript, one often needs to merge objects with a set of default values. This is typically done to create a new object that combines user-provided configurations with a standard set of default properties.

Using the Spread Operator

The preferred method to merge a default object with another object is by using the spread operator. The spread operator is concise and readable:

const defaultSettings = {
  theme: 'light',
  verbose: false,
  language: 'en'
};

const userSettings = {
  verbose: true
};

const mergedSettings = {
  ...defaultSettings,
  ...userSettings
};

Merged Object Result:

PropertyValue
theme‘light’
verbosetrue
language‘en’

In the table above, the verbose property from the userSettings takes precedence, overriding the default value.

TypeScript’s Type Inference

TypeScript infers the type of the mergedSettings object automatically. It will include all properties from the defaultSettings and userSettings. If a property is specified in both objects, the property from the second object userSettings is used.

Ensuring Types Align

To ensure compatibility between the default and user settings:

  • The user settings object should adhere to the shape defined by the default settings, with the flexibility to override specific keys.
  • TypeScript’s strong typing ensures that developers don’t accidentally introduce new properties or mismatch types.

TypeScript Merge Objects with Same Key

When merging two objects in TypeScript, handling properties with the same key requires attention. If two properties share the same key, TypeScript will determine the final value based on the order of the merge.

Example:

const objectA = { name: 'Alice', age: 25 };
const objectB = { name: 'Bob' };
const mergedObject = { ...objectA, ...objectB };
console.log(mergedObject);

In the code above, objectB overwrites the name property of objectA because objectB is unpacked after objectA. The resulting object is:

{ name: 'Bob', age: 25 }

Important Points:

  • The last object takes precedence.
  • Properties from later objects will overwrite those from earlier ones if they share the same key.
  • Using the spread operator (...) simplifies the merging process.

Type Considerations:

When handling types in merged objects:

  • Ensure the resulting object’s type reflects the possible keys and types from both objects.
  • The type of the merged object will be an intersection of the object types being merged.

Practical Use Case:

In practice, this behavior is often used to apply default settings or to update an object with new data coming from a user’s input or an API response.

Merging objects with TypeScript is straightforward. Developers need to be aware of the ordering and property overwrites to ensure the merged object meets their requirements.

TypeScript Merge Objects Ignore Undefined

When merging objects in TypeScript, one may encounter properties with undefined values. A prudent approach is to filter these out so they do not override existing property values with undefined.

The process is straightforward:

  1. Define a Helper Function: Create a function that removes properties with undefined values. This ensures the merged object contains only defined values.
  2. Use Object.fromEntries and Object.entries: These built-in methods facilitate the removal of undefined properties.
  3. Merge with Object.assign: After filtering, merge the objects with Object.assign, which will combine the properties.

Example Helper Function:

const removeUndefinedProps = (obj: Record<string, any>) => {
  return Object.fromEntries(Object.entries(obj).filter(([key, value]) => value !== undefined));
};

Merging Objects:

const obj1 = { name: 'Alice', age: 30 };
const obj2 = { age: undefined, email: 'alice@example.com' };
const mergedObject = Object.assign({}, obj1, removeUndefinedProps(obj2));

In the example above:

  • The age property in obj1 remains unchanged as obj2 had age as undefined.
  • The email property from obj2 is successfully merged into mergedObject.

Key advantages:

  • Type Safety: TypeScript infers correct property types, avoiding type errors.
  • Immutability: Objects are merged without mutating the original ones, following good practice in TypeScript.

By filtering undefined values during the merge, one maintains data integrity and avoids potential bugs where undefined values unintentionally override existing data.

Conclusion

Merging objects in TypeScript can be an efficient way to consolidate properties from multiple sources into a single entity. Developers have two primary methods at their disposal:

  • Spread Syntax (...): Offers a concise and readable way to combine objects.
  • Object.assign() Method: Copies properties from source objects to a target object.

Both methods are straightforward, with the spread syntax commonly preferred for its brevity and clarity. When merging objects:

  • Property Precedence: The last object’s properties will override those of the preceding ones if there are any overlapping keys.
  • Type Inference: TypeScript’s type system automatically infers the resulting object’s type and will raise errors if there are attempts to add or remove properties that do not conform to the inferred type.

In this Typescript tutorial, I have explained how to merge two objects in Typescript using different methods. I have explained the examples below:

  • Typescript how to merge two objects
  • Typescript merge all objects in array
  • Typescript merge objects overwrite
  • Typescript merge object with partial
  • Typescript merge object with default values
  • Typescript merge objects with same key
  • Typescript merge objects ignore undefined

You may also like:

>