TypeScript 泛型接口、泛型函数、泛型类

泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。使用泛型,通常有三种情况:泛型接口,泛型函数,泛型类,如下文所述。

1、泛型接口

接口既可以在面向对象编程中表示为行为的抽象,也可以用来描述对象的形状。声明泛型接口定义接口的时候也可以指定泛型,如下所示:声明一个名为 Identity 的简单接口,该接口具有两个属性(value 和 message)和两个用作属性类型的泛型类型变量(T 和 U)。

interface Identity<T, U> {
    value: T;
    message: U;
}

使用 Identity 接口作为对象类型来声明两个变量。

let myNumber: Identity<number, string> = {
    value: 25,
    message: 'Hello!'
}
let myString: Identity<string, number> = {
    value: 'Hello!',
    message: 25
}

2、泛型函数:将泛型接口声明为函数类型

声明一个名为 ProcessIdentity 的泛型接口,该接口包含方法的泛型签名 (value: T, message: U): T。 请注意,该方法没有名称。通过执行此操作,可以将其应用于具有匹配的类型签名的任何函数。

interface ProcessIdentity<T, U> {
    (value: T, message: U): T;
}

声明一个名为 processIdentity 的函数,该函数具有与 ProcessIdentity 接口相同的类型签名。

function processIdentity<T, U> (value: T, message: U) : T {
    console.log(message);
    return value
}

声明一个名为 processor 的函数类型变量,以 ProcessIdentity 接口作为变量类型,传递 number 作为 T 类型,string 作为 U 类型。 然后,将 processIdentity 函数分配给它。 现在,你可以将此变量用作代码中的函数,TypeScript 将验证这些类型。

let processor: ProcessIdentity<number, string> = processIdentity;
let myNumber = processor(100, 'Hello!');   // OK
let myString = processor('Hello!', 100);   // Type check error

3、泛型类:将泛型接口声明为类类型

声明一个名为 ProcessIdentity 的接口,该接口具有两个属性(value 和 message)和两个用作属性类型的泛型类型变量(T 和 U)。然后,添加方法 process 的一个泛型签名,该方法返回 T 类型的值。

interface ProcessIdentity<T, U> {
    value: T;
    message: U;
    process(): T;
}

定义一个实现 ProcessIdentity 接口的名为 processIdentity 的泛型类。在这种情况下,请在 processIdentity 类 X 和 Y 中命名变量类型。可以在接口和类中使用不同的变量名称,因为类型值沿链向上传播,而变量名称并不重要。

class processIdentity<X, Y> implements ProcessIdentity<X, Y> {
    value: X;
    message: Y;
    constructor(val: X, msg: Y) {
        this.value = val;
        this.message = msg;
    }
    process() : X {
        console.log(this.message);
        return this.value
    }
}

声明一个新变量并向其分配新的 processIdentity 对象,传入 number 和 string 作为 X 和 Y 变量类型,传入 number 和 string 作为参数值。

let processor = new processIdentity<number, string>(100, 'Hello');
processor.process();           // Displays 'Hello'
processor.value = '100';       // Type check error

4、直接定义泛型类

还可以声明没有接口的泛型类。 此示例将 processIdentity 声明为泛型类,但没有实现 ProcessIdentity 接口。

class processIdentity<T, U> {
    private _value: T;
    private _message: U;
    constructor(value: T, message: U) {
        this._value = value;
        this._message = message;
    }
    getIdentity() : T {
        console.log(this._message);
        return this._value
    }
}
let processor = new processIdentity<number, string>(100, 'Hello');
processor.getIdentity();      // Displays 'Hello'