学习篇-TypeScript-泛型

一、TypeScript-泛型
1. 泛型 【generics】
  • 什么是泛型

    • 泛指的类型,是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。
  • 应用场景:

    • 一个方法或者一个组件需要支持多种数据的类型,用户可以根据自己传入的数据类型来使用该方法或者组件。
  • 为什么不使用any类型?

    • any类型是接受任何类型的arg参数,传入值的类型和返回的值的类型只是可能相同,存在不确定性。
2. 泛型的定义和使用
  • 使用泛型可以创建泛型变量、泛型函数、泛型接口、泛型类,不可以创建泛型枚举和泛型命名空间
    • 创建泛型变量,表示这些参数是任意或者所有类型,只有使用的时候,才能被确定是什么类型。

      // first: T 和 second: T 就是一个泛型变量
      function join<T> (first: T, second: T) {
          return `${first} + ${second}`;
      }
      
      // User类中的firstName: T; 就是一个泛型变量
      class User<T>{
          firstName: T; 
      }
      // Resp接口中的code: T;就是一个泛型变量
      interface Resp<T> {
          code: T}
      
      
    • 创建泛型函数

      
      /**
       * 根据输入的长度和输入的值创建一个数组
       * @param length 输入的长度
       * @param value 输入的值
       * @returns Array<T> 输入类型的数组
       */
      function createArray<T>(length: number, value: T): Array<T> {
        let result: T[] = [];
        for (let i = 0; i < length; i++) {
          result[i] = value;
        }
        return result;
      }
      // 调用指定泛型
      createArray<string>(4, "a");
      // 根据ts的推断机制去推断泛型
      createArray(4, "a");
      
      // 多个泛型
      function connect<T, U>(first: T, second: U) {
        return `${first} + ${second}`;
      }
      
      
      • 函数名后添加,其中T用来表示任意输入类型。
      • 只有函数名添加了,在行参、返回值和函数体中才可以使用该泛型。
      • 再调用时指定泛型
      • 也可以让ts的推断机制去推断泛型,保证了代码精简和高可读性,但是在一些复杂的情况下,可能推断不出。
      • 当然也可以定义多个泛型
    • 创建泛型接口

      // 泛型接口
      interface ConfigFn<T> {
        (value: T): T;
      }
      
      function getData<T>(value: T): T {
        return value;
      }
      let myGetData: ConfigFn<string> = getData;
      
      myGetData("20");
      
    • 创建泛型类

      class DataManager<T> {
        constructor(private data: T[]) {}
      
        getItem(index: number): T {
          return this.data[index];
        }
      }
      
      const data = new DataManager<string>(["1"]);
      data.getItem(0);
      
      • 类有两个部分:静态部分和实例部分。泛型类指的是实例部分的类型,所以类的静态属性不能使用这个泛型类型。
3. 泛型约束
  • ,通过接口约束,关键字:extends

    interface Item {
      name: string;
    }
    // T泛型继承Item,表示后期使用的时候必须包含name属性
    class DataManager<T extends Item> {
      constructor(private data: T[]) {}
    
      getItem(index: number): string {
        return this.data[index].name;
      }
    }
    
    const data = new DataManager([{ name: "zhangsan" }]);
    data.getItem(0);
    
  • 在泛型约束中使用类型参数

    • 声明一个类型参数,且它被另一个类型参数所约束

      function getProperty(obj: T, key: K) {
          return obj[key];
      }
      
      let x = { a: 1, b: 2, c: 3, d: 4 };
      
      getProperty(x, "a"); // 编译正常
      getProperty(x, "m"); // 编译报错
      
      • 用属性名从对象里获取这个属性值。 并且我们想要确保这个属性存在于对象 obj上,因此需要在这两个类型之间使用约束。
  • 在泛型里使用类类型

    // 在TypeScript使用泛型创建工厂函数时,需要引用构造函数的类类型
    function create<T>(c: {new(): T; }): T {
        return new c();
    }
    // 使用原型属性推断并约束构造函数与类实例的关系
    class BeeKeeper {
        hasMask: boolean;
    }
    
    class ZooKeeper {
        nametag: string;
    }
    
    class Animal {
        numLegs: number;
    }
    
    class Bee extends Animal {
        keeper: BeeKeeper;
    }
    
    class Lion extends Animal {
        keeper: ZooKeeper;
    }
    
    function createInstance<A extends Animal>(c: new () => A): A {
        return new c();
    }
    
    createInstance(Lion).keeper.nametag;  
    createInstance(Bee).keeper.hasMask; 
    
4. 改进
  • 在 TypeScript 2.3 以后,可以为泛型中的类型参数指定默认类型。当使用泛型时没有在代码中直接指定类型参数,从实际值参数中也无法推测出时,这个默认类型就会起作用。

    function join<T = number>(first: T, second: T) {
      return `${first} + ${second}`;
    }
    

下一篇:学习篇-TypeScript-命名空间

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值