Last updated: Feb 28, 2024
Reading time·3 min
Use an interface or a type alias to type a nested object in TypeScript. You can set properties on the interface that point to nested objects.
The type of the object can have as deeply nested properties as necessary.
interface Person { name: string; address: { country: string; city: string; }; } const person: Person = { name: 'Bobby Hadz', address: { country: 'Chile', city: 'Santiago', }, };
We used an interface to type an object that has nested properties.
The address
property points to an object that has country
and city
properties of type string
.
You can also use a type alias to achieve the same result.
type Person = { name: string; address: { country: string; city: string; }; }; const person: Person = { name: 'Bobby Hadz', address: { country: 'Chile', city: 'Santiago', }, };
There are some minor differences between type aliases and interface, however, the examples above do the exact same.
You might also see examples online that type nested objects inline.
const person: { name: string; address: { country: string; city: string }; } = { name: 'Bobby Hadz', address: { country: 'Chile', city: 'Santiago', }, };
However, especially with nested objects, inline types are very difficult to read and should generally be avoided.
If you declare a nested object and initialize all of its key-value pairs, you can let TypeScript infer its type.
/** * const person: { name: string; address: { country: string; city: string; }; } */ const person = { name: 'Bobby Hadz', address: { country: 'Chile', city: 'Santiago', }, };
TypeScript is able to infer the type of the object based on the key-value pairs we have provided upon initialization.
If you don't have all of the values of the nested object ahead of time, you can mark them as optional, by using a question mark in the type's definition.
type Person = { name: string; address?: { // 👈️ address is optional country: string; city: string; }; }; const person: Person = { name: 'Bobby Hadz', }; person.address = { country: 'Chile', city: 'Santiago', };
We marked the address
property on the nested object as optional, so we aren't
required to provide it when initializing the object.
undefined
.You can use an index signature if you don't know all of the names of an object's properties in advance.
type Person = { name: string; address: { country: string; city: string; [key: string]: any; // 👈️ index signature }; }; const person: Person = { name: 'Bobby Hadz', address: { country: 'Chile', city: 'Santiago', }, }; person.address.street = 'Example str. 123'; person.address.postCode = 123;
The {[key: string]: any}
syntax is an
index signature in TypeScript and is used
when we don't know all the names of a type's properties and the shape of the
values ahead of time.
address
nested object is indexed with a string
, it will return a value of any
type.You might also see the index signature {[key: string]: string}
in examples. It
represents a key-value structure that when indexed with a string
returns a
value of type string
.
The example shows how even though we didn't define the address.street
or
address.postCode
properties, we are still able to set them on the nested
object.
You can learn more about the related topics by checking out the following tutorials: