Techumber
Home Blog Work

Understanding TypeScript 2.0's Mapped Types

Published on June 24, 2020

Introduction

In this post, we will delve into TypeScript 2.0’s mapped types and explore how they can be used to simplify complex type definitions in your codebase. We will start with the basics and then move on to more advanced topics…

Mapped Types

Mapped types are a powerful feature of TypeScript that allow you to map one type onto another. They are particularly useful when you want to reuse a type definition across multiple places in your codebase.

For example, let’s say you have a User interface with several properties:

interface User {
  id: number;
  name: string;
  email: string;
}

If you want to define a User object with a specific set of properties, you can use a mapped type like this:

type UserWithEmail = {
  [K in keyof User]: K extends 'email' ? string : never;
};

This will create a new type called UserWithEmail that has the same properties as User, but with an additional email property. The never keyword is used to indicate that any other properties that are not specified in the mapped type will be excluded from the resulting type.

Mapped types can also be used to create more complex types, such as interfaces or classes, by using a more complex mapping function. For example:

interface UserWithEmail {
  id: number;
  name: string;
  email: string;
}

type UserWithPassword = {
  [K in keyof UserWithEmail]: K extends 'password' ? string : never;
};

This will create a new type called UserWithPassword that has all the properties of UserWithEmail, plus an additional password property.

Mapped Types with Generics

Mapped types can also be used with generics to create more flexible and reusable type definitions. For example:

interface User<T extends string> {
  id: number;
  name: T;
}

type UserWithEmail = User<'email'>;
type UserWithPassword = User<'password'>;

This will create two new types called UserWithEmail and UserWithPassword, which have the same properties as the User interface, but with different types for the name property. The 'email' and 'password' strings are used to specify the type of the name property in each case.

Mapped types can be combined with other features of TypeScript, such as conditional types, to create even more flexible and powerful type definitions. For example:

type UserWithEmailOrPassword = {
  [K in keyof User]: K extends 'email' | 'password' ? string : never;
};

This will create a new type called UserWithEmailOrPassword that has all the properties of the User interface, but with an additional email and password property. The never keyword is used to indicate that any other properties that are not specified in the mapped type will be excluded from the resulting type.

Conclusion

Mapped types are a powerful feature of TypeScript that allow you to simplify complex type definitions in your codebase. They can be used with generics to create more flexible and reusable type definitions, and can be combined with other features of TypeScript to create even more powerful type definitions. By understanding how mapped types work, you can write more robust and maintainable code, and take advantage of the full potential of TypeScript’s type system.

Example of a TypeScript class using mapped types