Last updated: Feb 27, 2024
Reading timeยท4 min
Use the spread syntax (...) to merge objects in TypeScript.
The type of the final object will successfully be inferred, so trying to add or remove properties causes the type checker to show an error.
const obj1 = { name: 'Bobby Hadz', age: 30 }; const obj2 = { country: 'Chile' }; // ๐๏ธ const obj3: {country: string; name: string; age: number;} const obj3 = { ...obj1, ...obj2 }; // ๐๏ธ { name: 'Bobby Hadz', age: 30, country: 'Chile' } console.log(obj3);
We used the spread syntax (...) to unpack the properties from 2 objects into a third.
For example, if I try to add a new key-value pair to obj3
or try to delete a
key from the object, TypeScript will show an error.
const obj1 = { name: 'Bobby Hadz', age: 30 }; const obj2 = { country: 'Chile' }; // ๐๏ธ const obj3: {country: string; name: string; age: number;} const obj3 = { ...obj1, ...obj2 }; // ๐๏ธ {name: 'Bobby hadz', age: 30, country: 'Chile'} console.log(obj3); // โ๏ธ Error: Property 'test' does not exist // on type '{ country: string; name: string; age: number; }'. obj3.test = 'hello'; // โ๏ธ Error: The operand of a 'delete' operator must be optional. delete obj3['name'];
The type checker shows an error because the final object is already typed to
have the country
, name
and age
properties set to specific types.
However, you are able to update properties that exist on the object, as long as you provide a value that is the correct type.
const obj1 = { name: 'Bobby Hadz', age: 30 }; const obj2 = { country: 'Chile' }; // ๐๏ธ const obj3: {country: string; name: string; age: number;} const obj3 = { ...obj1, ...obj2 }; // ๐๏ธ {name: 'Bobby Hadz', age: 30, country: 'Chile'} console.log(obj3); obj3.name = 'Alice'; obj3.age = 29; console.log(obj3); // ๐๏ธ {name: 'Alice', age: 29, country: 'Chile'}
When merging objects, the order is important because if two objects have the same key, the object whose properties are unpacked later wins.
const obj1 = { name: 'Bobby Hadz', age: 30 }; const obj2 = { name: 'Alice' }; // ๐๏ธ const obj3: {name: string; age: number} const obj3 = { ...obj1, ...obj2 }; console.log(obj3); // ๐๏ธ {name: 'Alice', age: 30}
Both of the objects have the name
property, however, the keys of obj2
are
unpacked later, so its value overrides the value of the name
property in
obj1
.
You might also see the Object.assign()
method used to merge objects in
TypeScript.
const obj1 = { name: 'Bobby Hadz', age: 30 }; const obj2 = { country: 'Chile' }; // ๐๏ธ const obj3: {name: string; age: number} & {country: string} const obj3 = Object.assign({}, obj1, obj2); // ๐๏ธ {name: 'Bobby Hadz', age: 30, country: 'Chile'} console.log(obj3);
The first parameter the
Object.assign
method takes is the target
object - the object to which the properties of the
source objects are applied.
The next parameters the method takes are one or more source objects.
TypeScript is also able to infer the type of the new object using an intersection type.
&
and are used to combine existing object types. You can use the &
operator as many times as necessary to construct a type.If you try to add a new property to the object or delete an existing property, the type checker will throw an error.
const obj1 = { name: 'Bobby Hadz', age: 30 }; const obj2 = { country: 'Chile' }; // ๐๏ธ const obj3: {name: string; age: number} & {country: string} const obj3 = Object.assign({}, obj1, obj2); // ๐๏ธ {name: 'Bobby Hadz', age: 30, country: 'Chile'} console.log(obj3); // โ๏ธ Error: Property 'test' does not exist // on type '{ country: string; name: string; age: number; }'. obj3.test = 'hello'; // โ๏ธ Error: The operand of a 'delete' operator must be optional. delete obj3['name'];
This works in the same way as using the spread syntax (...).
You are still able to update the existing properties of the object, as long as you provide a value of the correct type.
const obj1 = { name: 'Bobby Hadz', age: 30 }; const obj2 = { country: 'Chile' }; // ๐๏ธ const obj3: {name: string; age: number} & {country: string} const obj3 = Object.assign({}, obj1, obj2); // ๐๏ธ {name: 'Bobby Hadz', age: 30, country: 'Chile'} console.log(obj3); obj3.name = 'Alice'; console.log(obj3); // ๐๏ธ {name: 'Alice', age: 30, country: 'Chile'}
The properties of the target object are overwritten by other objects that have the same properties later in the parameter order.
const obj1 = { name: 'Bobby Hadz', age: 30 }; const obj2 = { name: 'Alice' }; // ๐๏ธ const obj3: {name: string; age: number} & {country: string} const obj3 = Object.assign({}, obj1, obj2); console.log(obj3); // ๐๏ธ {name: 'Alice', age: 30}
This behavior is also consistent with the spread syntax (...).
You can learn more about the related topics by checking out the following tutorials: