Typescript一些常用的泛型工具
前言
本文将简要介绍Typescript一些常用泛型工具的使用技巧以及其相应的实现原理,进行相应的总结,如有不对之处,还望指出,感谢支持。
Typescript泛型工具
-
Partial
将传入的属性变为可选项
interface IPeople { title: string; name: string; } const people: Partial<IPeople> = { title: 'Delete inactive users' };
实现原理:
将映射对象类型
{ P in K : T }
与索引类型keyof T
查询结合使用来遍历已有对象类型的所有属性成员, 再对其属性成员设为可选属性。interface IPeople { title: string; name: string; } type MyPartial<T> = { [P in keyof T]?: T[P]; }; const people: MyPartial<IPeople> = { title: 'Delete inactive users' };
-
Record<K, T>
类型参数K提供了对象属性名联合类型,类型参数T提供了对象属性的类型
interface Person { name: string; } // 将x, y 作为Person的key type Peoples = Record<"x" | "y", Person>; const P: Peoples = { x: { name: '张三' }, y: { name: '李四' } }
实现原理:
通过
K extends keyof any
对泛型进行约束,约束在 any 的 key中, K可以是任意类型(联合类型、对象、枚举…),再通过映射对象类型{ P in K : T }
,将每一个属性成员转化为 T 类型interface Person { name: string; } type MyRecord<K extends keyof any, T> = { [P in K]: T; }; // 将x, y 作为Person的key type Peoples = MyRecord<"x" | "y", Person>; const P: Peoples = { x: { name: "张三", }, y: { name: "李四", }, };
-
Readonly
把传入的类型变为只读状态
interface Person { name: string; age: number; } const p: Readonly<Person> = { name: '张三', age: 22 } p.name = '李四'; // 无法分配到 "name" ,因为它是只读属性
实现原理:
与
Partial
实现原理类似,通过映射对象类型{ P in K : T }
方式遍历获取其所有属性成员,再统一设置为 readonlyinterface Person { name: string; age: number; } type MyReadonly<T> = { readonly [P in keyof T]: T[P]; }; const p: MyReadonly<Person> = { name: "张三", age: 22, }; p.name = "李四"; // 无法分配到 "name" ,因为它是只读属性
-
Required
把传入的类型变为必填状态
interface Person { name?: string; age?: number; } const p: Required<Person> = { name: '张三', age: 22 }
实现原理:
与
Partial
实现原理类似,通过映射对象类型{ P in K : T }
方式遍历获取其所有属性成员, 再统一通过“-”
修饰符移除“?”
修饰符,从而转变为必填状态interface Person { name?: string; age?: number; } type MyRequired<T> = { [P in keyof T]-?: T[P]; }; const p: MyRequired<Person> = { name: '张三', age: 22 }
-
Pick<T, S>
在 T 中,过滤掉非 S 的类型
interface IPerson { name: string; age: number; } type TP = Pick<IPerson, 'name'>; const p: TP = { age: 22, // 对象文字可以只指定已知属性,并且“age”不在类型“TP”中 name: '张三' }
实现原理:
通过
K extends keyof T
进行泛型约束,将 K 被约束在 T 的key中,不能超出这个范围,再通过映射对象类型{ key in K : T[key] }
,来约束每一个属性成员。interface IPerson { name: string; age: number; } type MyPick<T, K extends keyof T> = { [key in K]: T[key] } type TP = MyPick<IPerson, 'name'>; const p: TP = { age: 22, // 对象文字可以只指定已知属性,并且“age”不在类型“TP”中 name: '张三' }
-
Exclude<T, U>
该工具类型能够从类型T中剔除所有可以赋值给类型U的类型
type T0 = Exclude<"a" | "b" | "c", "a">; // 相当于 type T0 = "b" | "c" type T1 = Exclude<"a" | "b" | "c", "a" | "b">; // 相当于 type T1 = "c" type T2 = Exclude<string | number | (() => void), Function>; // 相当于 type T2 = string | number
实现原理:
表示如果
T
是U
的子类返回never
类型,如果不是返回T
类型。 当T
为联合类型的时候,它会自动分发条件。type MyExclude<T, U> = T extends U ? never : T; type T0 = MyExclude<"a" | "b" | "c", "a">; // 相当于 type T0 = "b" | "c" type T1 = MyExclude<"a" | "b" | "c", "a" | "b">; // 相当于 type T1 = "c" type T2 = MyExclude<string | number | (() => void), Function>; // 相当于 type T2 = string | number
-
Extract<T, U>
“Extract<T, U>”工具类型与“Exclude<T, U>”工具类型是互补的,它能够从类型T中获取所有可以赋值给类型U的类型
type T0 = Extract<'a' | 'b' | 'c', 'a' | 'f'>; // 相当于 type T0 = 'a'; type T1 = Extract<string | (() => void), Function>; // 相当于 type T1 = () => void; type T2 = Extract<string | number, boolean>; // 因为没有交集,相当于 type T2 = never;
实现原理:
与
Exclude<T, U>
实现方式类似type MyExtract<T, U> = T extends U ? T : never; type T0 = Extract<'a' | 'b' | 'c', 'a' | 'f'>; // 相当于 type T0 = 'a'; type T1 = Extract<string | (() => void), Function>; // 相当于 type T1 = () => void; type T2 = Extract<string | number, boolean>; // 因为没有交集,相当于 type T2 = never;
-
Omit<T, K>
在 T 中删除对应的 K
interface IPerson { name: string; age: number; } type TP = Omit<IPerson, 'age'>; const p: TP = { name: '张三' }
-
ReturnType
该工具类型能够获取函数类型T的返回值类型
// string type T0 = ReturnType<() => string>; // { a: string; b: number } type T1 = ReturnType<() => { a: string; b: number}>;
转载自:https://juejin.cn/post/6971341417893330952