实现typesctipt 内置工具类型(高级类型)

320 阅读4分钟

实现内置工具类型

Partial - 将类型T的所有属性改为可选

type Test1 = {
  data: 1;
  list: [];
  info?: {};
  num: number;
  str?: string;
};
type T1 = Partial<Test1>;

image.png

实现部分

  1. 接受一个类型参数
  2. 使用in和keyof遍历这个参数上的所有key
  3. 将所有属性添加?变为可选
type MyPartial<T> = {
  [K in keyof T]?: T[K];
};
type T2 = Partial<Test1>;

image.png

Required - 将类型T所有属性设为require必选

type Test1 = {
  data: 1;
  list: [];
  info?: {};
  num: number;
  str?: string;
};
type T1 = Required<Test1>;

image.png

实现部分 (和Partia反着来就行)

  1. 接受一个类型参数
  2. 使用in和keyof遍历这个参数上的所有key
  3. 使用-?来删除属性上的?然后就变为必选
type MyRequired<T> = {
  [K in keyof T]: T[K];
};
type T4 = MyRequired<Test1>;

image.png

Record - 构造一个类型,其属性名为K,属性值为V

type T5 = Record<1 | 2 | 3, string |number>;

image.png

实现部分

  1. 接受两个类型参数,一个是属性T,一个是值V
  2. 使用in遍历K,值取V即可
type MyRecord<T extends keyof any, V> = {
    [K in T]: V;
};
type T6 = MyRecord<1 | 2 | 3, string |number>;

image.png

Pick - 从类型T中挑选部分属性K来构造新的类型

type Test1 = {
  data: 1;
  list: [];
  info?: {};
  num: number;
  str?: string;
};
type T7 = Pick<Test1, "data" | "num">;

image.png

实现部分

  1. 接受两个类型参数,一个是属性T,一个是值K
  2. 使用in遍历K,这样就只取了传入的属性做新类型
  3. 值取T上的值,返回类型。
  type MyPick<T, K extends keyof T> = {
    [P in K]: T[P];
  };
  
  type T8 = MyPick<Test1, "data">;

image.png

Exclude - 从类型T中,剔除所有能赋值给U的属性

 type T9 = Exclude<"string" | "number", "string">;

image.png

实现部分

联合类型使用extends时会触发分发,就是每一个元素单独比较

  1. 接受两个类型参数,一个是属性T,一个是值K
  2. 判断T是否满足K,满足的话返回never代表删除
 type MyExclude<T, K> = T extends K ? never : T;
  
  type T10 = MyExclude<"string" | "number", "string">;

image.png

Extract - 从类型T中提取所有可以赋值给S的类型

 type T11 = Extract<"string" | "number", "string">;

image.png

实现部分 (与Exclude相反)

  1. 接受两个类型参数,一个是属性T,一个是值K
  2. 判断T是否满足K,满足的话返回这个T,不满足返回never代表删除
  type MyExtract<T, K> = T extends K ? T : never;
  
  type T12 = MyExtract<"string" | "number", "string">;

image.png

Omit - 从类型T中剔除所有能赋值给K的属性

与Exclude的区别在于Omit删除的是对象,Exclude删除的是联合类型

type Test1 = {
  data: 1;
  list: [];
  info?: {};
  num: number;
  str?: string;
};
type T1 = Omit<Test1, "data">;

image.png

实现部分

  1. 接受两个类型参数,一个是属性T,一个是值K
  2. 使用Pick与Exclude这两个类型配合使用,
  3. Exclude先拿到从T类型删除后的联合类型
  4. Pick将原类型和Exclude删除完剩下的类型组成新类型
type Test1 = {
  data: 1;
  list: [];
  info?: {};
  num: number;
  str?: string;
};

type MyOmit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
type T13 = MyOmit<Test1, "data">;

image.png

NonNullable - 从T中剔除null和undefined

  type T1 = NonNullable - <"1" | "2" | 3 | 4 | null | undefined>

image.png

实现部分

  1. 接受一个类型参数
  2. T extends触发分发
  3. 判断T是否满足null与undefined
  4. 满足条件返回never则删除,其余正常返回
  type MyNoNullable<T> = T extends null | undefined ? never : T;
  
  type T14 = MyNoNullable<"1" | "2" | 3 | 4 | null | undefined>;

image.png

ReturnType - 获得函数返回值的类型

type T1 = ReturnType<()=>'test'>

image.png

实现部分

  1. 接受一个类型参数
  2. T通过模式匹配来判断是否满足一个函数
  3. 使用infer关键字取出返回值并返回
type T1 = ReturnType<()=>'test'>
  type MyReturnType<T extends Function> = T extends (...args: any) => infer R
    ? R
    : never;
  
  type T15 = MyReturnType<() => 66>;

image.png

Readonly - 将T中所有属性设为只读

type Test1 = {
  data: 1;
  list: [];
  info?: {};
  num: number;
  str?: string;
};

type T1 = Readonly<Test1>

image.png

实现部分

  1. 接受一个类型参数
  2. in与keyof配合进行遍历
  3. 在每个属性上面加上readonly即可
  type MyRedoly<T> = {
    readonly [K in keyof T]: T[K];
  };
  
  type T16 = MyRedoly<Test1>;

image.png

Parameters - 获取函数的参数args

  type T1 = Parameters<(a: 1, b: 2) => {}>

image.png

实现部分 (与ReturnType相似,不过这次提取的是args)

  1. 接受一个类型参数
  2. T通过模式匹配来判断是否满足一个函数
  3. 使用infer关键字取出函数参数后返回
  type MyParameters<T extends (...args: any) => any> = T extends (
    ...args: infer A
  ) => any
    ? A
    : never;
  
  type T17 = MyParameters<(a: 1, b: 2) => {}>;

image.png

ConstructorParameters - 构造函数的参数

  type T1 = ConstructorParameters<new (a: 1) => 1>;

image.png

实现部分 (与函数的相似,只是多了个new)

  1. 接受一个类型参数
  2. T通过模式匹配来判断是否满足一个构造函数
  3. 使用infer关键字取出函数参数后返回
  type MyConstructorParameters<T extends new (...args: any) => any> =
    T extends new (...args: infer A) => any ? A : never;
  
  type T18 = MyConstructorParameters<new (a: 1) => 1>;

image.png

InstanceType - 构造函数的返回值

  type T1 = ConstructorParameters<new (a: 1) => 1>;

image.png 实现部分 (与函数的相似,只是多了个new)

  1. 接受一个类型参数
  2. T通过模式匹配来判断是否满足一个构造函数
  3. 使用infer关键字取出构造函数返回值后返回
  type MyInstanceType<T extends new (...args: any) => any> = T extends new (
    ...args: any
  ) => infer R
    ? R
    : any;
  
  type T19 = MyInstanceType<new () => 999>;

image.png