Borislav Hadzhiev
Wed Feb 23 2022·3 min read
Photo by Cristofer Maximilian
To add a property to an object in TypeScript, set the property as optional on the interface you assign to the object using a question mark. You can then add the property at a later point in time without getting a type error.
// ✅ Add specific property to object interface Person { name: string; age?: number; // 👈️ mark as optional so you can add later } const obj1: Person = { name: 'Tom', }; obj1.age = 30; // ✅ Add any property to object const obj2: Record<string, any> = {}; // 👇️ can now add any property to the object obj2.name = 'Tom'; obj2.age = 30; // ✅ Add any property, but type key-value // pairs you know in advance interface Animal extends Record<string, any> { name: string; age: number; } const obj3: Animal = { name: 'Alfred', age: 3 }; // 👇️ Can now add any property, but name and age are typed obj3.type = 'Dog';
The first example shows how to set the
age
property to optional on the Person
interface.
age
property can either be undefined
or a number
. This approach is the best when you know the name of the property and its value ahead of time as it keeps things type safe.Now you can initialize the object without the property, but are only able to set the property to the specific type later on.
interface Person { name: string; age?: number; // 👈️ mark as optional so you can add later } const obj1: Person = { name: 'Tom', }; obj1.age = 30; // ⛔️ Error: Type '"hello"' is not assignable // to type 'number | undefined'. obj1.age = 'hello';
If you try to assign a value that is not a number to the age
property, you'd
get an error.
The second example uses the
Record
utility type - Record<string, any>
.
// ✅ Add any property to object const obj2: Record<string, any> = {}; // 👇️ can now add any property to the object obj2.name = 'Tom'; obj2.age = 30;
The Record
utility type allows us to enforce the type of an object's values in
TypeScript, e.g. type Animal = Record<string, string>
. The Record
utility
type constructs an object type, whose keys and values are of specific type.
We passed any
as the type of the values in the object and string
as the keys
in the example.
This is very broad and allows us to add any property of any
type to the
object.
The third example shows how to specify the properties and the types in an object
that we know about and use the Record
utility type to allow the user to add
other properties.
// ✅ Add any property, but type key-value // pairs you know in advance interface Animal extends Record<string, any> { name: string; age: number; } const obj3: Animal = { name: 'Alfred', age: 3 }; // 👇️ Can now add any property, but name and age are typed obj3.type = 'Dog';
The interface we created requires the name
and age
properties but also
extends a type that allows any string properties with values of any
type.
This is better than just using the Record
utility type with string
keys and
any
values because we get type safety when it comes to the properties we
explicitly specified.
interface Animal extends Record<string, any> { name: string; age: number; } const obj3: Animal = { name: 'Alfred', age: 3 }; // ⛔️ Error: Type 'number' is not // assignable to type 'string'. obj3.name = 5;
Setting a property to the incorrect type causes an error because we've already
declared the name
property to be of type string
in the Animal
interface.