[路飞]_学习Typescript——泛型

403 阅读2分钟

从官方文档 Type Manipulation 开始学习ts

ts很牛B,因为在ts中可以:类型A由类型B计算得出。 “类型” 像一样,能通过 操作符被计算。ts中有专门的类型操作符(type operators)。 这种思想最简单的体现就是泛型。

Generics 泛型

定义对象的类型时使用类型变量泛型参数),即泛型generic)。泛型类型不再写死(hard code)。泛型用来让类型可重用(reusable)。

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

为了不写死,就必须引入变量机制(参数机制)。这里,Type就是变量参数)。这种值是类型的变量,称为类型变量(type variable)。定义函数时,定义函数类型,如果使用类型变量定义函数类型,这种函数就是泛型函数(generic functions)。

在定义函数类型时使用了类型变量,那么,在调用函数时要传入相应的类型值。如 identity 函数被调用,传入string作为类型变量类型值

let output = identity<string>("myString");

类型值可以由 ( "myString" ) 计算得出的时候(type argument inference),可以不传入类型值

let output = identity("myString");

什么是Array<Type> ?

function loggingIdentity<Type>(arg: Array<Type>): Array<Type> {
    return arg;
}

Array<Type>是使用了类型变量的类型定义,就是所谓的泛型定义。泛型定义Array<Type>的输出类型由泛型定义Array<Type>和类型变量Type类型值计算得出。

以下几种定义类型的语法的语义是相同:

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

let myIdentity: { <Type>(arg: Type)  : Type }  = identity;// as a call signature of an object literal type
let myIdentity:   <Type>(arg: Type) => Type    = identity;
interface GenericIdentityFn {// interface是对对象进行类型定义
                  <Type>(arg: Type)  : Type;// 在类型定义中使用类型变量(泛型)
}
interface GenericIdentityFn<Type> {// 类型变量升域,升域到interface级别
                        (arg: Type)  : Type;
}
let myIdentity:      GenericIdentityFn         = identity;
let myIdentity:      GenericIdentityFn<number> = identity;

像泛型函数的情况一样,在定义类时,定义类的类型时,使用泛型参数,这种类就是泛型类(generic classes

class GenericNumber<NumType> { // NumType是泛型参数
    zeroValue: NumType;
    add: (x: NumType, y: NumType) => NumType;
}

由类型来约束类型

到目前为止,我们知道由类型来约束,可以使得必须满足该类型。其实,类型也可以约束类型,使得类型必须满足另一类型。这样,形成类型A约束类型B类型B再约束值C的约束链路。约束类型B类型A可以是interface类型):

interface Lengthwise {// Lengthwise === 类型A
    length: number;
}

function loggingIdentity<Type extends Lengthwise>(arg: Type): Type {
    console.log(arg.length); 
    return arg;
}

类型A可以是类型变量

function getProperty<Type, Key extends keyof Type>(obj: Type, key: Key) {// 类型变量Type === 类型A
    return obj[key];
}

类型A可以是类对象(值):

class Animal {// Animal === 类型A
    numLegs: number = 4;
}

function createInstance<A extends Animal>(c: new () => A): A {
    return new c();
}