乐闻世界logo
搜索文章和话题

How to Combine Mapped Types and Conditional Types in TypeScript?

2024年7月4日 22:56

In TypeScript, Mapped Types and Conditional Types are two powerful type system features that can be used to create new types based on existing ones. Combining them allows for highly customized type transformations and validations. Below, I'll demonstrate how to use them together with a practical example.

Scenario Description

Assume we have an object type for user information, and we want to determine whether certain properties are optional based on the user's permission level.

Defining Base Types

First, define an interface UserInfo for user information:

typescript
interface UserInfo { id: number; name: string; email: string; role: string; }

Using Mapped Types and Conditional Types

We want to create a new type that determines whether the email property is optional based on the user's role attribute. In this example, we assume that only administrators (admin) must have the email property, while other users have it as optional.

typescript
type ConditionalEmail<T extends UserInfo> = { [K in keyof T]: K extends 'email' ? T['role'] extends 'admin' ? string : string | undefined : T[K] };

Parsing the Type Definition

In the above type definition, we use mapped types to redefine each property:

  • [K in keyof T] iterates over all properties of UserInfo.
  • K extends 'email' is a conditional type that checks if the current key is email.
  • If it is the email key, we further use the conditional type T['role'] extends 'admin' to verify if role is admin.
    • If it is admin, the type of email is string.
    • If not, the type of email is string | undefined (i.e., optional).
  • For non-email properties, we directly use the original type T[K].

Using This Type

typescript
const user1: ConditionalEmail<UserInfo> = { id: 1, name: 'Alice', role: 'admin', email: 'alice@example.com' }; const user2: ConditionalEmail<UserInfo> = { id: 2, name: 'Bob', role: 'user' // email is optional, so it can be omitted };

Summary

By using the above approach, we can dynamically adjust the types of other properties based on specific property values within the object. This method is particularly useful when handling complex objects with varying permissions. By combining mapped types and conditional types, TypeScript provides robust type system capabilities that enhance code safety and flexibility.

标签:TypeScript