How to Assign Types To Nested Objects In TypeScript
Tags: typescript, javascript, node, tutorial
Published: 2022-11-02 10:26:21

Objects are what you are dealing with working as a JavaScript developer, and needless to say, that holds true for TypeScript as well. TypeScript provides you with multiple ways to define type definitions for object properties. We'll look at a couple of them throughout this post, starting with simple examples and moving on to some advanced type definitions. 

## Using the `type` Keyword 
Object properties can be assigned type definitions using the `type` keyword in TypeScript. This is the easiest and preferred method to assign type definitions when dealing with simple objects. Here is an example of an `Airplane` type and an `airplane` object. 

```ts
// Defining Airplane Type
type Airplane = {
  model: string;
  flightNumber: string;
  timeOfDeparture: Date;
  timeOfArrival: Date;
};

// Creating airplane Object
const airplane: Airplane = {
  model: "Airbus A380",
  flightNumber: "A2201",
  timeOfDeparture: new Date(),
  timeOfArrival: new Date(),
};
```

### Nested Objects
If your object has a nested object, you can nest the type definitions using the type keyword itself. Here is an example of a nested object called `caterer` inside the `Airplane` type definition. 

```ts
type Airplane = {
  model: string;
  flightNumber: string;
  timeOfDeparture: Date;
  timeOfArrival: Date;
  caterer: {
    name: string;
    address: string;
    phone: number;
  };
};

const airplane: Airplane = {
  model: "Airbus A380",
  flightNumber: "A2201",
  timeOfDeparture: new Date(),
  timeOfArrival: new Date(),
  caterer: {
    name: "Special Food Ltd",
    address: "484, Some Street, New York",
    phone: 1452125,
  },
};
```

### Abstracting Nested Objects Into Separate Types
If you have large objects defining nested type definitions can become cumbersome. In such a case, you can define a separate `Caterer` type for the nested object. This will also abstract away the `Caterer` type from the `Airplane` type, allowing you to use the `Caterer` type in the other parts of your code.  

```ts
type Airplane = {
  model: string;
  flightNumber: string;
  timeOfDeparture: Date;
  timeOfArrival: Date;
  caterer: Caterer;
};

const airplane: Airplane = {
  model: "Airbus A380",
  flightNumber: "A2201",
  timeOfDeparture: new Date(),
  timeOfArrival: new Date(),
  caterer: {
    name: "Special Food Ltd",
    address: "484, Some Street, New York",
    phone: 1452125,
  },
};
```

### Using Index Signatures With Nested Objects
Index signatures can be used when you are unsure of how many properties an object will have but you are sure of the type of properties of an object. We can define another type called `Seat`, which can be the details of the passenger traveling on each seat of the `Airplane` type. We can use index signature to assign string type to all seat properties. 

```ts 
type Caterer = {
  name: string;
  address: string;
  phone: number;
};

type Seat = {
  [key: string]: string;
};

type Airplane = {
  model: string;
  flightNumber: string;
  timeOfDeparture: Date;
  timeOfArrival: Date;
  caterer: {
    name: string;
    address: string;
    phone: number;
  };
  seats: Seat[];
};

const airplane: Airplane = {
  model: "Airbus A380",
  flightNumber: "A2201",
  timeOfDeparture: new Date(),
  timeOfArrival: new Date(),
  caterer: {
    name: "Special Food Ltd",
    address: "484, Some Street, New York",
    phone: 1452125,
  },
  seats: [
    {
      name: "Mark Allen",
      number: "A3",
    },
    {
      name: "John Doe",
      number: "B5",
    },
  ],
};
```

## Interfaces to Assign Types to Object Properties
If you need to create classes to generate objects, using `interfaces` instead of the type keyword would be a better option. Here is an example of an `airplane` object created using the `Airplane` class, which extends the `IAirplane` interface. 

```ts
interface IAirplane {
  model: string;
  flightNumber: string;
  timeOfDeparture: Date;
  timeOfArrival: Date;
}

class Airplane implements IAirplane {
  public model = "Airbus A380";
  public flightNumber = "A2201";
  public timeOfArrival = new Date();
  public timeOfDeparture = new Date();
}

const airplane: Airplane = new Airplane();
```

### Nested Objects Using Interfaces 
Just like we used the `type` keyword, `interfaces` can also be used to strictly type nested objects with classes. 

```ts
interface ICaterer {
  name: string;
  address: string;
  phone: number;
}

interface ISeat {
  name: string;
  number: string;
}

interface IAirplane {
  model: string;
  flightNumber: string;
  timeOfDeparture: Date;
  timeOfArrival: Date;
}

class Caterer implements ICaterer {
  public name = "Special Food Ltd";
  public address = "484, Some Street, New York";
  public phone = 1452125;
}

class Seat implements ISeat {
  public name = "John Doe";
  public number = "A3";
}

class Airplane implements IAirplane {
  public model = "Airbus A380";
  public flightNumber = "A2201";
  public timeOfArrival = new Date();
  public timeOfDeparture = new Date();
  public caterer = new Caterer();
  public seats = [new Seat()];
}

const airplane: Airplane = new Airplane();
```

## What Can You Do Next 🙏😊
If you liked the article, consider subscribing to [Cloudaffle, my YouTube Channel](youtube.com/c/cloudaffle), where I keep posting in-depth tutorials and all edutainment stuff for software developers. You can also follow me on Hashnode; my profile handle - @[Cloudaffle](https://hashnode.com/@cloudaffle). Leave a like if you liked the article; it keeps my motivation high 👍.