美文网首页
TS笔记之 泛型

TS笔记之 泛型

作者: 伶念 | 来源:发表于2021-06-23 11:03 被阅读0次

    泛型

    介绍

    软件工程中,我们不仅要创建一致的定义良好的 API,同时也要考虑可重用性。 组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型,这在创建大型系统时为你提供了十分灵活的功能。可以使用泛型来创建可重用的组件,一个组件可以支持多种类型的数据。

    泛型之 Hello World

    这个函数会返回任何传入它的值

    function identity<T>(arg: T): T {
      return arg;
    }
    

    \color{#bf414a}{泛型} 有两种方法使用:

    1.传入所有的参数,包含类型参数:

    let output = identity<string>("myString"); // type of output will be 'string'
    

    2.类型推论 -- 编译器会根据传入的参数自动地帮助我们确定 T 的类型

    let output = identity("myString"); // type of output will be 'string'
    

    使用泛型变量

    把泛型变量 T 当做类型的一部分使用,而不是整个类型,增加了灵活性

    function loggingIdentity<T>(arg: Array<T>): Array<T> {
      console.log(arg.length); // Array has a .length, so no more error
      return arg;
    }
    

    泛型类型

    泛型接口:

    interface GenericIdentityFn<T> {
      (arg: T): T;
    }
    
    function identity<T>(arg: T): T {
      return arg;
    }
    
    let myIdentity: GenericIdentityFn<number> = identity;
    

    除了泛型接口,我们还可以创建泛型类。 注意,无法创建泛型枚举和泛型命名空间。

    泛型类

    泛型类看上去与泛型接口差不多。 泛型类使用( <>)括起泛型类型,跟在类名后面。

    class GenericNumber<T> {
      zeroValue: T;
      add: (x: T, y: T) => T;
    }
    
    let myGenericNumber = new GenericNumber<number>();
    myGenericNumber.zeroValue = 0;
    myGenericNumber.add = function (x, y) {
      return x + y;
    };
    

    泛型类指的是实例部分的类型,所以类的静态属性不能使用这个泛型类型。

    泛型约束

    我们想要限制函数去处理任意带有.length 属性的所有类型。 只要传入的类型有这个属性,我们就允许,就是说至少包含这一属性。 为此,我们需要列出对于 T 的约束要求。

    为此,我们定义一个接口来描述约束条件。 创建一个包含 .length 属性的接口,使用这个接口和 extends 关键字来实现约束:

    interface Lengthwise {
      length: number;
    }
    
    function loggingIdentity<T extends Lengthwise>(arg: T): T {
      console.log(arg.length); // Now we know it has a .length property, so no more error
      return arg;
    }
    

    现在这个泛型函数被定义了约束,因此它不再是适用于任意类型:

    loggingIdentity(3); // Error, number doesn't have a .length property
    

    在泛型约束中使用类型参数

    function getProperty(obj: T, key: K) {
      return obj[key];
    }
    
    let x = { a: 1, b: 2, c: 3, d: 4 };
    
    getProperty(x, "a"); // okay
    getProperty(x, "m"); // error: Argument of type 'm' isn't assignable to 'a' | 'b' | 'c' | 'd'.
    

    在泛型里使用类类型

    在 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; // typechecks!
    createInstance(Bee).keeper.hasMask; // typechecks!
    

    相关文章

      网友评论

          本文标题:TS笔记之 泛型

          本文链接:https://www.haomeiwen.com/subject/wefbyltx.html