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'