泛型编程(下)

介绍一些 TS 内置工具类型的用法及实现

Readonly & Mutable

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
type Person = { id: number; name: string; age: number };

type Readonly<T> = {
readonly [K in keyof T]: T[K];
};
type X1 = Readonly<Person>;
// {
// readonly id: number;
// readonly name: string;
// readonly age: number;
// }

type Mutable<T> = {
-readonly [K in keyof T]: T[K];
};
type X9 = Mutable<Readonly<Person>>;
// {
// id: number;
// name: string;
// age: number;
// }

注意:

  • Mutable 并不是 TS 内置的函数
  • -readonly [] 表示去掉属性前面的 Readonly

Partial & Required

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
type Person = { id: number; name: string; age: number };

type Partial<T> = {
[K in keyof T]?: T[K];
};
type X2 = Partial<Person>;
// {
// id?: number;
// name?: string;
// age?: number;
// }

type Required<T> = {
[K in keyof T]-?: T[K];
};
type X3 = Required<Person>;
// {
// id: number;
// name: string;
// age: number;
// }

注意 -?,表示去掉属性的可选,变为必选

Exclude & Extract

1
2
3
4
5
type Exclude<A, B> = A extends B ? never : A;
type X5 = Exclude<1 | 2 | 3, 1 | 2>; // 3

type Extract<A, B> = A extends B ? A : never;
type X6 = Extract<1 | 2 | 3, 2 | 4>; // 2

按照之前讲的乘法分配律,有如下理解过程:

1
2
3
4
5
6
7
8
type X5 = 1 | 2 | 3 extends 1 | 2 ? never : A

type X5 =
| 1 extends 1 | 2 ? never : 1 // never
| 2 extends 1 | 2 ? never : 2 // never
| 3 extends 1 | 2 ? never : 3 // 3

type X5 = never | never | 3 // 3

X6 的理解过程同 X5,这里不赘述

Omit & Pick

1
2
3
4
5
6
7
8
9
10
11
12
13
type Person = { id: number; name: string; age: number };

type Omit<T, Key extends keyof T> = Pick<T, Exclude<keyof T, Key>>;
// 或者
type Omit<T, Key> = {
[K2 in keyof T as (K2 extends Key ? never : K2)]: T[K2];
};
type X7 = Omit<Person, 'name' | 'age'>; // { id: number }

type Pick<T, Key extends keyof T> = {
[K2 in Key]: T[K2];
};
type X8 = Pick<Person, 'name' | 'age'>; // { name: string; age: number }

Key extends keyof T 是一个泛型约束,约束所传的 key 必须包含在 keyof T 中,即必须是 'id' | 'name' | 'age' 的子集

Record

1
2
3
4
5
type Record<Key extends string | number | symbol, Value> = {
[k in Key]: Value;
};

type X4 = Record<string, string>; // { [x: string]: string }

ReturnType

1
2
3
4
5
function f(a: number, b: number) {
return 'a + b'
}

type F = ReturnType<typeof f> // string

其他

这里推荐一个用于练习 TS 类型体操的 repo:TypeScript 类型体操姿势合集

看看别人的体操:


(●'◡'●)ノ♥