泛型对前端开发人员来说会比较陌生,其实它可以被理解成是一种预先设置的数据类型,在后面通过推导得出真实的类型后再替换。在 typescript 中有很多的工具泛型,可以帮助我们更加灵活地处理类型,简化类型编程的过程,提高生产力。
关键词
要熟悉工具泛型及其原理,首先要掌握 typescript 的关键词
typeof
获取变量的类型
keyof
keyof T,获取类型 T 的所有键组成的联合类型,keyof 也被称为 索引类型查询操作符
interface IPerson {
id: string;
age: number;
}
type IPersonKeys = keyof IPerson; // 'id' | 'age'
type IPersonKeys = IPerson[keyof IPerson]; // string | number
[]
索引访问操作符,可以进行索引访问
interface T {
K: string;
}
type TypeK = T[K]; // string
in
可以对联合类型进行遍历。通过 [K in Keys] 可以实现映射类型,从旧类型中创建新类型的一种方式
type Index = 'a' | 'b' | 'c'
type FromIndex = { [K in Index]?: number }
const index_1: FromIndex = { b: 1, c: 2 }
const index_2: FromIndex = { b: 1, d: 3 } // 报错,不能添加d属性
extends
- 用来扩展已有的类型
interface IAnimal = {
name: string;
}
interface ICat extends IAnimal {
action: string;
}
// 等价于
type ICat = IAnimal & {
action: string;
}
- 对类型进行条件限定,比如判断两种类型是否相等:
type IsEqualType<A, B> = A extends B ? (B extends A ? true : false) : false;
- 对于 T extends U ? X : Y 来说,还存在一个特性,当 T 是一个联合类型时,会进行条件分发。这一点对于理解后面的工具泛型很关键
type Demo = string | number;
type IsString<T> = T extends string ? "yes" : "no";
type IsDemoString = IsString<Demo>; // 'yes' | 'no';
实际上,extends 的转换类似于下面这一步:
(string extends string ? 'yes' : 'no') | (number extends string ? 'yes' : 'no')
infer
在有条件类型的 extends 子语句中,允许出现 infer 声明,它会引入一个待推断的类型变量,简单说就是用它取到函数返回值的类型来使用
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any;
readonly
将属性标记为只读
工具泛型
Record
将 K 中所有的属性的值转化为 T 类型
type Record<K extends keyof any, T> = { [P in K]: T };
Pick
从 T 中取出一系列 K 的值
type Pick<T, K extends keyof T> = { [P in K]: T[P] };
Exclude
从 T 中排除 U
type Exclude<T, U> = T extends U ? never : T;
Extract
从 T 中提取 U
type Extract<T, U> = T extends U ? T : never;
Omit
相当于 Pick + Exclude, 实现忽略对象某些属性功能,Pick+Exclude
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
Partial
将 T 中的属性都变为可选属性
type Partial<T> = { [k in keyof T]?: T[k] };
Required
将 T 中的属性都变为必选属性
type Required<T> = { [k in keyof T]-?: T[k] };
Readonly
将 T 中的属性都变为只读属性
type Readonly<T> = { readonly [k in keyof T]: T[k] };
Mutable
将 T 中的属性都变为可读属性
type Mutable<T> = { -readonly [k in keyof T]: T[k] };
ReturnType
获取函数的返回值的类型
type ReturnType<T extends (...args: any[]) => any> = T extends (
...args: any[]
) => infer R
? R
: never;
Parameters
获取函数的参数的类型
type Parameters<T extends (...args: any[]) => any> = T extends (
...args: infer P
) => any
? P
: never;