TypeScript 映射类型与条件类型(附形象记忆法)
一、映射类型(Mapped Types)详解
1.1 基础概念
映射类型允许我们基于现有类型的属性,创建一个新类型,通常用于批量修改属性。
核心语法:
1 | type MappedType<T> = { |
1.2 常见内置映射类型
1.2.1 Readonly<T>
将所有属性设为只读:
1 | interface User { |
形象记忆:就像给所有门加上”禁止进入”的锁(readonly)
1.2.2 Partial<T>
将所有属性变为可选:
1 | type PartialUser = Partial<User>; |
形象记忆:就像把所有必填字段变成”选填”(?)
1.2.3 Required<T>
将所有属性变为必填(与 Partial 相反)
1 | type RequiredUser = Required<PartialUser>; |
1.2.4 Record<K, T>
创建一个对象类型,其键为 K,值为 T
1 | type UserRoles = Record<string, "admin" | "user" | "guest">; |
形象记忆:就像创建一个”键值对”的表格
1.2.5 Pick<T, K>
从 T 中选取指定的属性 K
1 | type UserName = Pick<User, "name">; |
形象记忆:就像从菜单中”点菜”(只选需要的)
1.2.6 Omit<T, K>
从 T 中排除指定的属性 K
1 | type UserWithoutAge = Omit<User, "age">; |
形象记忆:就像从套餐中”删除”不想要的项
1.3 自定义映射类型
1.3.1 添加前缀/后缀
1 | type AddPrefix<T, Prefix extends string> = { |
形象记忆:就像给所有文件名加前缀
1.3.2 条件修改属性
1 | type MakeNullable<T> = { |
形象记忆:就像给所有必填字段加上”可为空”的选项
二、条件类型(Conditional Types)详解
2.1 基础语法
1 | T extends U ? X : Y |
如果类型 T 可以赋值给 U,则结果为 X,否则为 Y
2.2 常见用法
2.2.1 类型判断
1 | type IsString<T> = T extends string ? true : false; |
形象记忆:就像做选择题(是/否)
2.2.2 提取数组元素类型
1 | type ElementType<T> = T extends (infer U)[] ? U : never; |
形象记忆:就像从容器中”提取”内容
2.2.3 分支处理
1 | type ResponseType<T> = T extends { error: any } |
形象记忆:就像交通信号灯(不同条件走不同分支)
2.3 高级用法
2.3.1 分布式条件类型
当 T 是联合类型时,条件类型会自动分发:
1 | type ToArray<T> = T extends any ? T[] : never; |
形象记忆:就像批量处理邮件(每个收件人收到单独的邮件)
2.3.2 条件类型递归
1 | type DeepReadonly<T> = { |
形象记忆:就像俄罗斯套娃,一层层深入
三、形象记忆法总结
| 概念 | 记忆技巧 |
|---|---|
Readonly<T> |
给所有属性加”禁止修改”标签 |
Partial<T> |
把所有必填变成”选填” |
Pick<T,K> |
从菜单中”点菜” |
Omit<T,K> |
从套餐中”删除”不想要的 |
AddPrefix<T,P> |
给文件名加前缀 |
MakeNullable<T> |
给必填字段加”可为空”选项 |
IsString<T> |
做选择题(是/否) |
ElementType<T> |
从容器中”提取”内容 |
| 分布式条件类型 | 批量处理邮件(每个收件人单独处理) |
| 条件类型递归 | 俄罗斯套娃,一层层深入 |