Working with Mapped Types in TypeScript

Tutorial 1 of 5

Introduction

The goal of this tutorial is to familiarize you with Mapped Types in TypeScript, a feature that allows you to create new types based on existing ones. We will explore how to utilize them to enhance the flexibility and maintainability of your code.

By the end of this tutorial, you should be able to:

  • Understand the concept of mapped types in TypeScript.
  • Use mapped types to create new types based on existing ones.
  • Apply best practices when working with mapped types.

To follow this tutorial, you should have a basic understanding of TypeScript and generic types.

Step-by-Step Guide

Mapped Types

Mapped types are a way in TypeScript to create new types based on old ones, with the ability to modify properties. They are often used when you want to make all properties in an object readonly, optional, or have some other quality.

A simple example of a mapped type is Partial<T>, which makes all properties of an object optional.

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

In this example, T is a type variable, P is a property key, and T[P] is the type of property P in T. The ? makes all properties optional.

Readonly Mapped Type

Let's consider another example. If we want to make all properties of an object readonly, we can use the Readonly<T> mapped type.

type Readonly<T> = {
  readonly [P in keyof T]: T[P];
};

Best Practices

When working with mapped types:

  • Be aware of the type of object you're working with. Not all types are created equal, and some will behave differently than others when mapped.
  • Be careful when making properties optional or readonly. This can cause unexpected behavior if not handled correctly.

Code Examples

Example 1: Partial Mapped Type

Here's an example of using the Partial<T> mapped type.

interface Todo {
  title: string;
  description: string;
}

type PartialTodo = Partial<Todo>;

let todo: PartialTodo = {
  title: "Learn TypeScript"
};

In this example, we define a Todo interface with title and description properties. Then we use the Partial<T> mapped type to create a new type PartialTodo where all properties are optional.

Example 2: Readonly Mapped Type

Let's see an example of using the Readonly<T> mapped type.

interface Config {
  host: string;
  port: number;
}

const config: Readonly<Config> = {
  host: "localhost",
  port: 8000
};

config.port = 9000; // Error: Cannot assign to 'port' because it is a read-only property.

In this example, we define a Config interface and then create a Readonly<Config> object. If we try to modify the properties, TypeScript will throw an error.

Summary

In this tutorial, you've learned how to:

  • Understand and use mapped types in TypeScript.
  • Create new types based on existing ones using mapped types.
  • Apply best practices when working with mapped types.

Next, you might want to explore conditional types, which are another powerful feature in TypeScript's type system. The TypeScript handbook is also a great resource for further learning.

Practice Exercises

  1. Create a Person interface with name and age properties. Then use the Partial<T> mapped type to create a new type where all properties are optional.

  2. Create a Settings interface with multiple properties. Then use the Readonly<T> mapped type to create a new readonly object.

  3. Create a Mutable<T> mapped type that removes readonly from all properties.

For solutions and further practice, check out the TypeScript Playground where you can experiment with different types and see the results in real time.