ZHANGYU.dev

October 14, 2023

Typescript 工具泛型

TypeScript4.1 min to read

这些工具函数定义在lib.es5.d.ts,我的typescript版本是3.5.2

首先需要理解几个关键概念

keyof

keyoftypescript 2.1新增的关键字,keyof T返回的是T的属性名称(键名),keyof T的类型被认为是string的子类

interface Person {    name: string;    age: number;    location: string;}type K1 = keyof Person; // "name" | "age" | "location"type K2 = keyof Person[];  // "length" | "push" | "pop" | "concat" | ...type K3 = keyof { [x: string]: Person };  // string

in

in可以遍历联合类型

interface User{    name: string;    age: number;    phone: number;}type d = {    [p in keyof User]: string;}// type d = {//     name: string;//     age: string;//     phone: string;// }

Mapped Types 映射类型

一个常见的任务是将一个已经存在类型中的所有属性变为可选

Person

interface Person {    name: string;    age: number;    location: string;}

它的可选属性类型应该是:

interface PartialPerson {    name?: string;    age?: number;    location?: string;}

应用映射类型,PartialPerson可以写为Person的广义转换

type Partial<T> = {    [P in keyof T]?: T[P];};type PartialPerson = Partial<Person>;

Partial

Partial就是上述映射类型的举例,能够将属性转为可选属性

type Partial<T> = {    [P in keyof T]?: T[P];};

Required

将所有的属性转换为必选

type Required<T> = {    [P in keyof T]-?: T[P];};

Partial中,多了一个?,而这里是-?,它的意思是将?取掉,所以这里的每一个属性都是必选的

interface User{    name: string;    age?: number;    phone: number;}type r = Required<User>// type r =  {//    name: string;//    age: number;//    phone: number;// }

Readonly

将所有属性变为只读属性

type Readonly<T> = {    readonly [P in keyof T]: T[P];};

readonly表示只读属性,属性只能在初始化时赋值

Pick

T中取出部分属性,K是必须是T的键名的子枚举

type Pick<T, K extends keyof T> = {    [P in K]: T[P];};
interface User{    name: string;    age: number;    phone: number;}type p = Pick<User,"name"|"phone">// type p = {//     name: string;//     phone: number;// }

Record

K类型转换为T类型

type Record<K extends keyof any, T> = {    [P in K]: T;};
interface User{    name: string;    age: number;    phone: number;}type r = Record<keyof User, string>// type r = {//     name: string;//     age: string;//     phone: string;// }

这里需要注意的是Record<K,T>K必须是联合类型,需要写上keyof

Exclude

T中排除U中包含的类型

type Exclude<T, U> = T extends U ? never : T;
interface User{    name: string;    age: number;    phone: number;}type e = Exclude<keyof User, "age"|"phone">// type e = "name"

Extract

T中提取包含U的属性

type Extract<T, U> = T extends U ? T : never;
interface User{    name: string;    age: number;    phone: number;}type e = Extract<keyof User, "age"|"type"|"address">// type e = "age"

Omit

构造一个类型,这个类型包含除了T类型之外的K类型的属性

type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
interface User{    name: string;    age: number;    phone: number;}type o = Omit<User, "age">;// type o = {//     name: string;//     phone: number;// }

NonNullable

T中去掉nullundefined

type NonNullable<T> = T extends null | undefined ? never : T;
type options = "debug" | "release" | null | undefined;type n = NonNullable<options>;// type n = "debug" | "release"

Parameters

获取函数中的参数类型的元组

type Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never;
type UserFunc = (name: string, phone: number) => voidtype a = Parameters<UserFunc>// type a = [string, number]

出现了一个新关键字inferinfer可以表示extends语句中待推断的类型变量

ConstructorParameters

获取构造函数中的参数类型的元组

type ConstructorParameters<T extends new (...args: any) => any> = T extends new (...args: infer P) => any ? P : never;
class UserClass  {    constructor(name:string,phone:number) {};}type a = ConstructorParameters<typeof UserClass>// type a = [string, number]

ReturnType

获取函数返回值的类型

type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;
type User = { name: string };type UserFunc = () => User;type a = ReturnType<UserFunc>// type a = {//     name: string;// }

InstanceType

获取构造函数函数返回值的类型

type InstanceType<T extends new (...args: any) => any> = T extends new (...args: any) => infer R ? R : any;
class UserClass  {    constructor(name:string,phone:number) {};}type a = InstanceType<typeof UserClass>// type a = UserClass

这些内置工具函数的参数还是有一些不理解,有些是直接传类型,有些是传keyof后的联合类型,有一些又是typeof,需要加省学习