TypeScript中infer关键字的介绍与使用(一)

177 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第3天,点击查看活动详情

infer

  1. 啥是inferinfer是在泛型约束的extends条件语句中起到声明占位符作用的关键字。
  2. 示例
    • extends条件语句就类似于三元运算
      type ExtendsExample<T> = T extends object ? T : string;
      
      // 这里因为{}是object的子类型,满足条件语句,所以a的最终类型为{}
      type a = ExtendsExample<{}> 
      
      // 这里因为boolean不是object的子类型,不满足条件语句,
      // 所以a的最终类型为string
      type b = ExtendsExample<boolean>  
      
    • 声明参数类型占位符
      type InferExample<T> = T extends (param: infer P) => void ? P : T;
      // 满足条件语句, 且在这里占位符P的类型为promise<number>,
      // 所以这里的infer2,类型为promise<number>
      type infer1 = InferExample<(promise: Promise<number>) => void> 
      
      // infer2类型为string,即传入的泛型T类型。因为不满足条件语句
      type infer2 = InferExample<string> 
      
    • 声明返回值类型占位符
      type InferExample2<T> = T extends () => infer P ? P : T;
      
      // 满足条件语句, 且在这里占位符P的类型为promise<number>,
      // 所以这里的infer2,类型为promise<number>
      type infer3 = InferExample2<() => Promise<number>> 
      
      // infer2类型为string,即传入的泛型T类型。因为不满足条件语句
      type infer4 = InferExample2<string> 
      
    • 声明泛型具体化类型占位符
      type InferExample3<T> = T extends Promise<infer P> ? P : T;
      
      // 满足条件语句, 且在这里占位符P的类型为number,
      // 所以这里的infer2,类型为number
      type infer5 = InferExample3<Promise<number>>
      
      // infer2类型为string,即传入的泛型T类型。因为不满足条件语句
      type infer6 = InferExample3<string> 
      
  3. 完善泛型工厂函数,使其能够动态传入构造器参数且传值时有相应的提示 (泛型工厂函数详情可以看
    class Tearcher {
     name: string;
     age: number;
     constructor(name: string, age: number) {
       this.name = name;
       this.age = age;
     }
    
     introduce() {
       console.log(`My name is ${this.name},${this.age} years old`);
     }
    }
    
    type ConstructorType<T> = new (...arg: any) => T;
    
    // 获取类构造器参数类型的工具类型,这里的T为“typeof 具体类”
    type GetConstructorArgsType<T extends new (...arg: any[]) => any> =
      T extends new (...args: infer P) => any ? P : any;
    
    // 类型为元组[name: string, age: number],Tearcher构造器的形参类型
    type TearcherArgsTyped = GetConstructorArgsType<typeof Tearcher>;
    
    function createGenericityInstanceFactory<
      T,
      R extends new (...arg: any[]) => any
    >(Constructor: ConstructorType<T>, Params: GetConstructorArgsType<R>) {
      return new Constructor(...Params);
    }
    
    // 这里teacher实例对象的类型为Tearcher
    // 且第二个参数的类型必须为[name: string, age: number]
    const tear2 = creatInstanceFactory<Tearcher, typeof Tearcher>(
      Tearcher,
      ["张三", 14]
    );
    
    tear2.introduce(); // My name is 张三,14 years old