Mapped types

While Generic types help you to create “General types”,

Mapped Types will help you transform existing types.

Again, let’s look at what the TypeScript documentation says:

In a mapped type, the new type transforms each property in the old type in the same way.

But, how do we “transform each property”, in other terms, how do we iterate over a type properties?

Let’s take a look at the following keywords: in and keyof .

Imagine we have the following User type:

All those User properties are required on API side, however, in our single page application, the on-boarding is divided in 2 steps, meaning that the non-saved user record might have undefined properties, let’s call it the LocalUser type.

How to create this on-boarding LocalUser type?

One solution might be to create a copy of the User type with “nullable” properties:

However, for a maintainability point of view, it’s a shame to duplicate the User type.

This is when Mapped Types will help us:

LocalUser is just the User type with same optional properties.

Let’s look at this, step by step:

keyof User will be a type that would be any value in key of User , so the following union type: ‘first_name’ | ‘last_name’ | ‘city’ | ‘twitter_handle’

K in will give us a iterator of User properties union type.

will give us a of properties union type. Finally, User[K] , called a index type, will bring us the type of the K index of User .

In short, when K is city , then User[K] will be CityShortFormat .

Let’s end with a combination of mapped type and generics:

type Partial<T> = { [P in keyof T]?: T[P]; }

type LocalUser = Partial<User>;