TypeScript泛型的介绍与应用

377 阅读3分钟

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

1. 泛型介绍

  1. 啥是泛型? 个人认为,泛型就是将数据类型进行参数化。
  2. 泛型的使用
    • 类中使用泛型——泛型类
      // 格式如下
      // 定义时
      class 类名<泛型形参> // 形参名一般为A-Z其中的字母,形参可以有多个
      
      // 调用 实例化
      const 对象实例 = 类名<具体的数据类型,如stringbooleanobject等>();
      
      // 具体例子
      class Queue<T> {
        protected queue: Array<T> = []
        enQueue(ele: T) {
          this.queue.unshift(ele)
        }
        deQueue(): T | undefined {
          return this.queue.pop()
        }
      }
      
      const queue = new Queue<string>();
      queue.enQueue(1)
      queue.enQueue(2)
      
      console.log(queue.deQueue()); // 1
      console.log(queue.deQueue()); // 2
      
    • 泛型接口
      interface Queue<T extends Object> {
        queue: Array<T>;
        enQueue(ele: T): void;
        deQueue(): T | undefined;
      }
      
    • 泛型方法
      function 
      
    • 泛型的默认类型
      1. 如果不传入具体的数据类型,那么这里默认为unknown
      2. 可以在定义类的时候,指定默认类型
      3. 注意,默认类型的生效时间是在调用类/方法等之后
      // 如果不传入具体的数据类型,那么这里默认为unknown
      const queue2 = new Queue();
      
      // 您也可以在定义类的时候,指定默认类型
      class Queue<T = string> {
        ....
      }
      
      class Queue<T = string> {
        ....
        // 报错:类型“T”上不存在属性“localeCompare”。
        // 这里的类型还是泛型“T”,而非我们设置的默认类型。
        // 默认类型的生效时间是在调用类/方法等之后
        sortEle() {
          this.queue.sort((a, b) => a.localeCompare(b))
        }
      }
      
    • 泛型约束 通过使用extends关键字来限制泛型的具体化数据类型的范围.
      class Queue<T extends object> {
        protected queue: Array<T> = []
        enQueue(ele: T) {
          this.queue.unshift(ele)
        }
        deQueue(): T | undefined {
          return this.queue.pop()
        }
      }
      
      // 报错:类型“string”不满足约束“object”。
      const queue = new Queue<string>();
      
      // 此时默认类型为object
      const queue4 = new Queue();
      
      当我们传入具体数据类型时,只能传入extends后面数据类型的子类型或本身。
      // 正确
      const queue2 = new Queue<object>();
      
      type SubObject = {
        name: string,
        age: number
      }
      
      // 正确
      const queue3 = new Queue<SubObject>();
      
  3. 泛型工厂函数
    • 工厂函数定义:即构造函数,可以通过new进行实例化
    • 泛型工厂函数定义:一个可以创建任意类对象的通用函数 a. 使用场景:一是再一些不方便直接new类名()格式来创建对象,如装饰器当中 b. 在一些项目测试或者调试中简化代码使用。
    • 示例:
      // 通用函数类型
      type CommonFunc = (...args: any) => any
      interface CommonFuncInterface {
        (...args: any): any
      }
      const func: CommonFuncInterface = function (count: string): void { }
      
      
      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 = new (...arg: any) => any
      
      // 工厂函数
      function createInstanceFactory(Constructor: ConstructorType) {
        // 这里的参数暂时为固定,下一篇的infer会有改变
        return new Constructor('张三', 14)
      }
      
      // 这里teacher实例对象的类型为any,调用对象的方法时没有提示,所以下面引入了泛型
      const tear1 = createInstanceFactory(Tearcher);
      
      tear1.introduce() // My name is 张三,14 years old
      
      // 泛型工厂函数
      function createGenericityInstanceFactory<T>(Constructor: { new(...args: any): T }) {
        return new Constructor('张三', 14)
      }
      
      // 这里teacher实例对象的类型为Tearcher
      const tear2 = creaeteGenericityInstanceFactory<Tearcher>(Tearcher);
      
      tear2.introduce() // My name is 张三,14 years old