变型:协变、逆变、不变性

讲的最好的协变、逆变

条件类型

T extends U ? T : never,T如果可以分配给U,则返回类型T,否则返回never;

注意,当T是联合类型时,相当于对T的每种子类型单独应用条件类型,然后再把结果联合,如:

1
2
3
4
5
type a = 1 | 2 | "3" | "4";

type b<T> = T extends number ? T : never;

type c = b<a>; // 1 | 2

相当于

1
2
3
4
5
type a = 1 | 2 | "3" | "4";

type b<T> = T extends number ? T : never;

type c = b<1> | b<2> | b<"3"> | b<"4">; // 1 | 2

推断类型

T extends (a: infer R) => R ? R : never,a的实际类型未知,用infer R先假设R是a的类型,有点类似于泛型,只不过推断类型是自动推断的,泛型需要传入泛型参数或预设默认值。

内置类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
// 构建一个所有属性可选的T
type Partial<T> = {
[P in keyof T]?: T[P];
};

// 构建一个所有属性必须的T
type Required<T> = {
[P in keyof T]-?: T[P];
};

// 构建一个所有属性只读的T
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};

// 构建一个T的子类型,包含指定属性名K
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
};

// 构建一个有属性名K,值类型全是T的类型
type Record<K extends keyof any, T> = {
[P in K]: T;
};

// 从T中提取能兼容U的子类型的联合类型
type Extract<T, U> = T extends U ? T : never;

// 与Extract相反,从T中提取不能兼容U的子类型的联合类型
type Exclude<T, U> = T extends U ? never : T;

// 与Pick相反,构建一个T的子类型,不包含指定属性名K
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;

// 提取T中不兼容null|undefined的子类型,NonNullable<string|null> 等价于 string
type NonNullable<T> = T extends null | undefined ? never : T;

// 提取函数参数类型,结果类似于元组
type Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never;

// 提取构造函数参数类型,结果类似元组
type ConstructorParameters<T extends abstract new (...args: any) => any> = T extends abstract new (...args: infer P) => any ? P : never;

// 提取函数返回值类型
type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;

// 根据构造函数类型构造出实例类型
type InstanceType<T extends abstract new (...args: any) => any> = T extends abstract new (...args: any) => infer R ? R : any;

// 大写
type Uppercase<S extends string> = intrinsic;

// 小写
type Lowercase<S extends string> = intrinsic;

// 首字母大写
type Capitalize<S extends string> = intrinsic;

// 首字母小写
type Uncapitalize<S extends string> = intrinsic;