共计 3375 个字符,预计需要花费 9 分钟才能阅读完成。
highlight: github
theme: juejin
前言
Typescript
中默认内置了很多工具泛型,通过应用这些工具,能够使得咱们定义类型更加灵便,高效。本文将会介绍罕用泛型工具的应用技巧,以及对其实现原理进行相应的解析,如果有谬误的中央,还望指出。
Partial\<T>
作用 :将传入对象类型 T
的属性变为 可选属性。
示例:
interface Person {
name: string;
age: number;
}
const tom: Partial<Person> = {name: "Tom",};
Partial<Person>
等价于
interface Person {
name?: string;
age?: number;
}
实现原理:
- 通过关键字
keyof
将传入对象类型的键值转换为联结类型。 - 通过关键字
in
遍历联结类型,即遍历对象的键值。 - 通过类型映射,将对象的属性转换为 可选属性
type MyPartial<T> = {[P in keyof T]?: T[P];
};
Readonly\<T>
作用 :把传入对象类型 T
属性变为 只读属性。
示例:
interface Person {
name: string;
age: number;
}
const tom: Readonly<Person> = {
name: "Tom",
age: 18;
};
tom.age = 22 // error
Readonly<Person>
等价于
interface Person {
readonly name: string;
readonly age: number;
}
实现原理:
与 Partial
相似:
- 通过关键字
keyof
将传入对象类型的键值转换为联结类型。 - 通过关键字
in
遍历联结类型,即遍历对象的键值。 - 通过类型映射,将对象的属性转换为 只读属性
type Readonly<T> = {[P in keyof T]-?: T[P];
};
Required\<T>
作用 :把传入对象类型 T
属性变为 必填属性。
示例:
interface Person {
name?: string;
age?: number;
}
let tom: Required<Person>
tom = {
name: "Tom",
age: 18;
};
// ok
tom = {name: "Tom",};
// error
实现原理:
与 Partial
相似:
- 通过关键字
keyof
将传入对象的键值转换为枚举类型。 - 通过关键字
in
遍历枚举类型,即遍历对象的键值。 - 通过类型映射,再对立通过
-?
修饰符移除?
修饰符,从而转变为 必填状态。
type Required<T> = {Required [P in keyof T]: T[P];
};
Record\<K,T>
作用:它用来生成一个属性名为 K
,属性值类型为 T
的对象类型汇合。
示例:
// 疾速生成一个 Person 对象
type Person = Record<"name" | "country", string>;
const Tom: Person = {name: "Tom", country: "America"};
实现原理:
- 通过
K extends keyof any
对K
参数进行束缚,将其束缚为任意类型any
的键值。 - 通过
in
对键值汇合K
进行遍历,而后生成类型为T
的键值对汇合。
type MyRecord<K extends keyof any, T> = {[P in K]: T;
};
Exclude\<T,K>
作用:从类型 T
中排除所有能够赋值给类型 U
的类型。
示例:
// 从 "a" | "b" | "c" 中排除掉 "a" 类型
type T1 = Exclude<"a" | "b" | "c", "a">;
// T1 = "b" | "c"
// 从 string | number | boolean 中排除掉 string 类型
type T2 = Exclude<string | number | boolean, string>;
// T2 = number | boolean
实现原理:
-
通过条件类型
T extends U ? never : T
对T
参数进行判断:- 如果
T
可赋值给U
,那么返回never
(即排除掉T
)。 - 如果
T
不可赋值给U
,那么返回T
。
- 如果
- 通过 分布式条件类型 ,如果
T
为联结类型,则将条件类型的后果散发为 联结类型。
type Exclude<T, U> = T extends U ? never : T;
Extract\<T,K>
作用:与 Exclude
相同,从类型 T
中提取所有能够赋值给类型 U
的类型。
示例:
// 从 "a" | "b" | "c" 中提取出 "a" 类型
type T1 = Extract<"a" | "b" | "c", "a">;
// T1 = "a"
// 从 string | number | boolean 中提取出 string 类型
type T2 = Extract<string | number | boolean, string>;
// T2 = string
type T3 = Extract<string | (() => void), Function>;
// 相当于 type T3 = () => void;
实现原理:
与 Exclude
相似:
-
通过条件类型
T extends U ? never : T
对T
参数进行判断:- 如果
T
可赋值给U
,那么返回T
。 - 如果
T
不可赋值给U
,那么返回never
(即排除掉T
)。
- 如果
- 通过 分布式条件类型 ,如果
T
为联结类型,则将条件类型的后果散发为 联结类型。
type Extract<T, U> = T extends U ? T : never;
Pick\<T,K>
作用:在 T
中,摘选出 K
属性。
示例:
interface Person {
name: string;
age: number;
}
// 从 Person 中摘选出 name 属性
type PickPerson = Pick<Person, "name">;
const tom: PickPerson = {name: "Tom",};
实现原理:
- 通过
K extends keyof T
对K
参数进行束缚,将其束缚为T
的键值范畴内。 - 通过
in
对键值汇合K
进行遍历,而后生成类型为T
的键值对汇合。
type Pick<T, K extends keyof T> = {[P in K]: T[P];
};
Omit\<T,K>
作用:在 T
中,剔除掉 K
属性。
示例:
interface Person {
name: string;
age: number;
}
// 从 Person 中剔除掉 name 属性
type OmitPerson = Omit<Person, "name">;
const tom: OmitPerson = {age: 18,};
实现原理:
- 通过
K extends keyof T
对K
参数进行束缚,将其束缚为T
的键值范畴内。 - 通过
Exclude<keyof T, K>
将类型汇合T
中的K
类型排除掉。 - 通过
Pick<T,Exclude<keyof T, K>>
在T
中摘选出排除掉K
的T
的属性。
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
ReturnType\<T>
作用:获取函数的返回值类型。
示例:
type Fun = () => string;
// 获取 Fun 返回值的类型
type T1 = ReturnType<Fun>; // T1 = string
type T2 = ReturnType<() => { x: number; y: number}>;
// T2 = {x: number, y: number}
实现原理:
- 通过
extends
对T
参数进行束缚,(...args: any) => any
示意一个函数类型,即T
参数的类型必须是一个 函数类型。 T extends U ? X : Y
是条件类型(留神和之前示意束缚的extends
做辨别),其中T
是泛型参数,U
是 条件局部,X
是符合条件的返回后果,Y
是不符合条件的返回后果。- 推断类型
infer
的作用是:在条件类型外部申明一个 类型变量 。(...args: any) => infer R
是条件类型的 条件局部,它申明了一个类型变量R
,用来存储函数的返回类型。 -
T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any
示意:- 如果
T
是函数类型((...args: any) => infer R
),则返回R
, 即函数的返回类型。 - 如果
T
不是函数类型((...args: any) => infer R
),则返回any
。
- 如果
type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R
? R
: any;
参考资料
- TypeScript 中文手册
- TypeScript 内置工具泛型
正文完
发表至: typescript
2023-09-25