泛型

125 阅读3分钟

可以使用泛型来创建可重用的组件,一个组件可以支持多种类型的数据。 这样用户就可以以自己的数据类型来使用组件。

  1. 简介

    // <T> 表示 函数接收的类型,这个类型,是在调用函数的时候传进来的,这样,这个函数就可以支持多个类型
    // 这个函数 就形成了一个泛型  不同于any 传入值得类型, 函数返回的类型 都是明确地
    
    function identify<T>(arg: T): T {
        return arg;
    }
    
    
    // 那我们如何调用这个函数呢 有两种方法
    // 方法一 传入所有的参数,包含类型参数  明确地指明 要传入的值得类型
    
    let output = identify<string>("zhj");
    
    
    // 方法二  利用类型推论-- 编译器 自己去推断 我们传入的类型
    
    let output = identify("zhj");
    
  2. 泛型变量

    // 从上面的例子可以看出,T 是个类型,然后函数,使用的时候,是当整个类型使用的,那么我可以只把T 当做类型的一部分进行使用吗???
    
    // 此时  这个方法应该是报错的,因为你可以传入任何的类型,number 类型是没有length属性的。 因为没有办法明确到底是哪种类型,因为T 是作为一整个类型使用的
    function identify<T>(arg: T): T {
        return arg.length;  
    }
    
    
    // 那么T 如何作为类型的一部分使用呢??? 其实就是就是明确的指出 参数会是什么类型
    // 这样就可以了,明确地指出参数是一个数组类型, 但是内部的属性,是什么类型,使用时传递就可以了
    
    function identify<T>(arg: T[]): T[] {
        return arg.length;
    }
    
    
  3. 泛型类型

    // 泛型函数的类型与非泛型函数的类型没什么不同,只是有一个类型参数在最前面,像函数声明一样:
    
    function identity<T>(arg: T): T {
        return arg;
    }
    
    let myIdentity: <T>(arg: T) => T = identity;
    
    
    // 泛型接口
    interface GenericIdentityFn<T> {
        (arg: T): T;
    }
    
    function identity<T>(arg: T): T {
        return arg;
    }
    
    let myIdentity: GenericIdentityFn<number> = identity;
    
  4. 泛型类

    //泛型类看上去与泛型接口差不多。 泛型类使用( <>)括起泛型类型,跟在类名后面。
    
    // 泛型类 只能针对类的实例部分,静态部分不能使用这个泛型类型
    
    class Animam<T> {
        num: T,
        add: (x: T, y: T) => T;
    }
    
    let animal = new Animal<number>();
    
  5. 泛型约束

    // 在2 中,我们想用参数的.length属性,但是我们传进来的参数类型是不确定的,不知道参数是不是有这个属性
    
    // 我们可以利用接口, 对泛型T 进行约束,必须包含某种条件 才可以访问
    
    
    // 关键字 extends
    
    interface immlate {
        length: number;
    }
    
    //T 继承接口,T 必须符合接口的条件才可以使用
    function greet<T  extends immlate>(num: T): T {
        return num.length
    }
    
  6. 在泛型约束中使用类型参数

    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'.
    
  7. 在泛型中使用类类型

    //使用原型属性推断并约束构造函数与类实例的关系。
    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!