成为 TypeScript 高手 - 快来做体操
快来做体操 —— 本文带你感受 ts 类型系统的魅力,提升 ts 的能力。
ts 类型体操,是对 ts 类型计算的一种戏称,因为 ts 的类型非常灵活,且复杂度够深。
做操之前,先保证了解这些:
- JavaScript 语法
- TypeScript 语法
基础
TypeScript 的类型系统也可以做很多运算,现在我们来了解一些基础逻辑运算。
交叉 &
对类型做合并
1 | type NewType = { a: number } & { b: string }; |
联合 |
表示可以是多种类型之一
1 | type Union = "a" | "b" | 1 | 2; |
约束 extends
可以为模板类限制类型
1 | interface Base { |
条件 T extends U ? X : Y
类似三元表达式,即如果 T 是 U 的子类型,那么类型是 X,否则是 Y
1 | type IsString<T> = T extends string ? string : number; |
索引查询 keyof T
获取类型的所有键的联合类型
1 | const obj = { |
索引访问 T[K]
取类型中索引的类型
1 | type TestInterface = { |
配合 keyof
还可以获取所有索引的联合类型
1 | type TestInterface = { |
遍历索引 in
用于遍历联合类型,常配合 keyof 使用,可以根据已有类型创建新类型
1 | const obj = { |
再比如复制出一份只读类型,给所有索引都加上 readonly
修饰
1 | type Readonly<T> = { |
或去掉 readonly
1 | type NotReadonly<T> = { |
索引重映射 as
在索引后面加个 as 语句,可以对索引类型做过滤和转换
比如仅保留类型为 number
的索引
1 | type FilterNumber<T> = { |
再比如给索引都加上前缀 prefix-
1 | type AddPrefix<T> = { |
再如,交换类型的 key 和 value
1 | type Flip<T extends Record<any, any>> = { |
TypeScript 内置高级类型
内置高级类型是利用基础语法,做出各种变换,从而支持高级类型。类型体操也是同样的过程和操作
Readonly
把索引改为只读,用 in 操作符遍历索引,映射为一个新类型,并将索引改为 readonly
1 | type Readonly<T> = { |
Partial
把索引变为可选,用 in 操作符遍历索引,映射为一个新类型,给索引加上 ?
1 | type Partial<T> = { |
Required
把索引变为必选,用 in 操作符遍历索引,映射为一个新类型,给索引移除 `?
1 | type Required<T> = { |
Pick
用 in 遍历自定义参数,配合联合类型,生成新的映射类型
1 | type Pick<T, K extends keyof T> = { |
Record
用 in 遍历自定义参数,创建新的映射类型
1 | type Record<K extends keyof any, T> = { |
Exclude
排除联合类型的部分类型
1 | type Exclude<T, U> = T extends U ? never : T; |
Extract
取联合类型的部分类型,与 Exclude
相反
1 | type Extract<T, U> = T extends U ? T : never; |
Omit
删除类型中的部分索引
1 | type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>; |
简单体操
未完待续