函数、构造器、索引类型的模式匹配例子

114 阅读2分钟

1、函数的模式匹配

1、提取参数的类型

type GetParameters15<Func extends Function> =
  Func extends (...args: infer Args) => unknown ? Args : never;

type test15=GetParameters15<(answer:boolean,count:number)=>number>
//type test15 = [answer: boolean, count: number]

2、提取返回值类型

type GetReturnType16<Func extends Function> =
  Func extends (...args: any[]) => infer ReturnType
  ? ReturnType : never;


type test16 = GetReturnType16<(answer: boolean, count: number) => 'hello'>
//type test16 = "hello"

3、让编译器能够检查出 this 指向的错误

class Hello17 {
  name: string;

  constructor() {
    this.name = "dong";
  }

  hello(this: Hello17) {
    return 'hello, I\'m ' + this.name;
  }
}

const test17 = new Hello17();
test17.hello();
const test17_1 = new Hello17();
//test17.hello.call({ a: 11 }); 会报错 必须是Hello17这个类

this 类型同样也可以通过模式匹配提取出来

class Hello17 {
  name: string;

  constructor() {
    this.name = "dong";
  }

  hello(this: Hello17) {
    return 'hello, I\'m ' + this.name;
  }
}

const test17 = new Hello17();

type GetThisParameterType17_1<T>
  = T extends (this: infer ThisType, ...args: any[]) => any
  ? ThisType
  : unknown;

type test17_2 = GetThisParameterType17_1<typeof test17.hello>;
//type test17_2 = Hello17

2、构造器

构造器和函数的区别是,构造器是用于创建对象的,所以可以被 new。

通过模式匹配提取构造器的参数和返回值的类型

1、取出构造器返回的实例类型

interface Hello18 {
  name: string;
}

interface Hello18Constructor {
  new(name: string): Hello18;
}

//这里的 Hello18Constructor 返回的是 Hello18 类型的实例对象
//这个也可以通过模式匹配取出来
type GetInstanceType18<
  ConstructorType extends new (...args: any) => any
> = ConstructorType extends new (...args: any) => infer InstanceType
  ? InstanceType
  : any;
//类型参数 ConstructorType 是待处理的类型,通过 extends 约束为构造器类型。
//用 ConstructorType 匹配一个模式类型
//提取返回的实例类型到 infer 声明的局部变量 InstanceType 里,返回 InstanceType。
//这样就能取出构造器对应的实例类型:
  
type test18=GetInstanceType18<Hello18Constructor>
//type test18 = Hello18

2、提取构造器的参数类型

interface Hello18 {
  name: string;
}

interface Hello18Constructor {
  new(name: string): Hello18;
}

type GetConstructorParameters19<
  ConstructorType extends new (...args: any) => any
> = ConstructorType extends new (...args: infer ParametersType) => any
  ? ParametersType
  : never;
//类型参数 ConstructorType 为待处理的类型,通过 extends 约束为构造器类型。
//用 ConstructorType 匹配一个模式类型
//提取参数的部分到 infer 声明的局部变量 ParametersType 里,返回 ParametersType。

type test19 = GetConstructorParameters19<Hello18Constructor>
//type test19 = [name: string]

3、索引类型的模式匹配

1、通过模式匹配的方式提取 ref 的值的类型

type GetRefProps20<Props> =
  'ref' extends keyof Props
  ? Props extends { ref?: infer Value | undefined }
  ? Value
  : never
  : never;
//类型参数 Props 为待处理的类型。
//通过 keyof Props 取出 Props 的所有索引构成的联合类型,
//判断下 ref 是否在其中,也就是 'ref' extends keyof Props。
//如果有 ref 这个索引的话,就通过 infer 提取 Value 的类型返回,否则返回 never。
 
type test20 = GetRefProps20<{ ref?: 'helloref', name: 'hello' }>
//type test20 = "helloref"

参考链接:

juejin.cn/book/704752…