TypeScript工具类型:你实际上需要知道的那些

TypeScript的内置工具类型优雅地解决了常见的类型转换问题。许多TypeScript用户不了解所有这些——以下是在生产代码中真正有价值的那些。

Partial、Required和Readonly

Partial<T>使T的所有属性变为可选。对于只传递你想要更改的字段的更新操作很有用:`function updateUser(id: string, updates: Partial<User>) {…}`。Required<T>是其逆——使所有可选属性变为必需。对于具有默认值的配置对象规范化很有用。Readonly<T>使所有属性变为只读。用于创建后不应修改的配置对象以及你希望保证不可变性的函数参数。DeepReadonly(非内置,但通常有类型定义):Readonly只适用于一个层级——`type DeepReadonly<T> = { readonly [K in keyof T]: DeepReadonly<T[K]> }`递归地应用。

Pick和Omit

Pick<T, K>构造只包含T中指定键的类型:`type UserPreview = Pick<User, ‘id’ | ‘name’ | ’email’>`。当你想要接口的子集用于API响应或组件props时使用。Omit<T, K>是其逆——排除指定的键:`type UserWithoutPassword = Omit<User, ‘password’ | ‘salt’>`。组合:这两个工具类型消除了维护并行接口定义的需要。不是分别从User定义UserPublic,而是使用Omit派生它——对User的任何更改都会自动传播到UserPublic。常见模式:用于数据库创建DTO的`type CreateInput = Omit<User, ‘id’ | ‘createdAt’ | ‘updatedAt’>`。

Record

Record<K, V>构造一个具有K类型键和V类型值的对象类型:`type StatusMap = Record<‘pending’ | ‘active’ | ‘inactive’, User[]>`。这比`{ [key: string]: User[] }`更精确,因为它指定了哪些键是有效的。穷举性检查的好处:`const statusMap: Record<Status, User[]> = { pending: [], active: [] }` — TypeScript会报错因为’inactive’缺失。这在编译时捕获缺失的键,对于switch-case穷举性和数据映射特别有价值。

Extract、Exclude和NonNullable

Extract<T, U>从T中提取所有可分配给U的联合成员:`type StringOrNumber = Extract<string | number | boolean, string | number>`给出`string | number`。Exclude<T, U>是其逆——删除可分配给U的类型:`type NoBoolean = Exclude<string | number | boolean, boolean>`给出`string | number`。NonNullable<T>从T中删除null和undefined:`type SafeString = NonNullable<string | null | undefined>`给出`string`。当处理来自外部API的联合类型时,你想缩窄类型以及在组合条件类型时,这些特别有用。实际使用:`type EventHandler<T extends Event> = Extract<MouseEvent | KeyboardEvent | FocusEvent, T>`用于类型化的事件处理。

上一篇 TypeScript Utility Types: The Ones You Actually Need to Know
下一篇 The Canary Islands: Which Island for What Kind of Trip