DEV Community

Dharan Ganesan
Dharan Ganesan

Posted on

Day 48: Mapped Types

What Are Mapped Types? 🤔

Mapped types are a way to create new types by transforming the properties of an existing type. Essentially, they allow you to iterate over the properties of one type and create a new type based on those properties. This can be incredibly useful for scenarios like creating read-only or optional versions of types or filtering out specific properties.

Basic Syntax 📝

type MappedType<T> = {
  [P in keyof T]: NewType;
};
Enter fullscreen mode Exit fullscreen mode

Here's a breakdown of what each part means:

  • {}: Encloses the mapped type definition.

  • T represents the original type.

  • P represents each property in the original type.

  • keyof T produces a union type of all keys in T.

  • in is a keyword that denotes the mapping process.

  • NewType is the type you want to assign to each property in the new type.

Creating a Read-Only Type 🔒

One common use case for mapped types is to create a read-only version of an object type. Let's say we have a type representing a user:

type User = {
  id: number;
  name: string;
  email: string;
};
Enter fullscreen mode Exit fullscreen mode

We can create a read-only version of this type using a mapped type:

type ReadOnlyUser = {
  readonly [K in keyof User]: User[K];
};
Enter fullscreen mode Exit fullscreen mode

In this example, [K in keyof User] iterates over each property in the User type, and User[K] retains the type of each property. The readonly modifier makes each property read-only.

Now, if we try to modify a property of ReadOnlyUser, TypeScript will throw an error:

const user: ReadOnlyUser = {
  id: 1,
  name: "Alice",
  email: "alice@example.com",
};

user.name = "Bob"; // Error: Cannot assign to 'name' because it is a read-only property.
Enter fullscreen mode Exit fullscreen mode

Creating Optional Properties ❓

Mapped types can also be used to make properties optional. Let's say we have a type representing a configuration:

type AppConfig = {
  apiKey: string;
  loggingEnabled: boolean;
  maxRequestsPerMinute: number;
};
Enter fullscreen mode Exit fullscreen mode

We can create a version of this type where all properties are optional like this:

type OptionalConfig = {
  [K in keyof AppConfig]?: AppConfig[K];
};
Enter fullscreen mode Exit fullscreen mode

Now, all properties in OptionalConfig are optional:

const config: OptionalConfig = {
  apiKey: "my-api-key",
  // No need to specify other properties
};
Enter fullscreen mode Exit fullscreen mode

Filtering Out Properties 🧹

Mapped types also allow us to filter out specific properties from a type. Let's say we want to create a type that excludes the loggingEnabled property from AppConfig:

type WithoutLogging = {
  [K in Exclude<keyof AppConfig, "loggingEnabled">]: AppConfig[K];
};
Enter fullscreen mode Exit fullscreen mode

In this example, we use the Exclude utility type to remove the "loggingEnabled" property from the keys of AppConfig. The resulting type, WithoutLogging, does not contain the loggingEnabled property:

const config: WithoutLogging = {
  apiKey: "my-api-key",
  maxRequestsPerMinute: 100,
};
Enter fullscreen mode Exit fullscreen mode

Top comments (0)