TypeScript 的泛型(Generics)是 TypeScript 的一个非常强大的特性,它允许你在编译时定义组件,这些组件可以工作于多种类型的数据上。泛型可以创建可重用的组件,这些组件是独立于任何特定类型的。这意味着你可以编写灵活且可重用的函数、接口和类,这些组件可以接受多种类型的数据作为参数。
泛型函数
泛型函数是在调用时能够接收一个或多个类型参数作为参数的函数。
function identity<T>(arg: T): T {
return arg;
}
let output = identity<string>("myString"); // 类型参数为 string
let output2 = identity(42); // TypeScript 会自动推断出类型参数为 number
在这个例子中,identity
函数是一个泛型函数,它接受一个类型参数 T
和一个参数 arg
,该参数的类型也是 T
。函数直接返回它的参数,其返回值的类型也是 T
。
泛型接口
泛型接口是定义了组件形状的接口,这些组件可以工作于多种类型上。
interface GenericIdentityFn<T> {
(arg: T): T;
}
function identity<T>(arg: T): T {
return arg;
}
let myIdentity: GenericIdentityFn<number> = identity;
在这个例子中,GenericIdentityFn
是一个泛型接口,它描述了一个接受单个参数并返回相同类型参数的函数。然后,我们使用这个接口来指定 myIdentity
函数的类型,这个函数能够处理 number
类型的参数。
泛型类
泛型类是在类定义时引入类型参数的一种方式。
class GenericNumber<T> {
zeroValue: T;
add: (x: T, y: T) => T;
constructor(zeroValue: T, add: (x: T, y: T) => T) {
this.zeroValue = zeroValue;
this.add = add;
}
}
let myGenericNumber = new GenericNumber<number>(0, function(x, y) { return x + y; });
console.log(myGenericNumber.add(1, 2)); // 输出: 3
在这个例子中,GenericNumber
是一个泛型类,它接受一个类型参数 T
。这个类有两个属性:zeroValue
和 add
。zeroValue
的类型是 T
,而 add
是一个函数,它接受两个类型为 T
的参数并返回一个类型为 T
的结果。
泛型约束
有时,你可能想对泛型进行约束,以便它只能被某些类型使用。你可以通过 extends
关键字来约束泛型类型。
interface Lengthwise {
length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T {
console.log(arg.length); // 现在我们知道 arg 有 length 属性
return arg;
}
loggingIdentity({length: 10, value: 3}); // 正确
loggingIdentity({value: 3}); // 错误: 没有 length 属性
在这个例子中,我们创建了一个泛型 T
,它受到 Lengthwise
接口的约束。这意味着 T
必须有一个 length
属性,并且 loggingIdentity
函数现在可以接受任何具有 length
属性的对象。
泛型是 TypeScript 中的一个非常有用的特性,它允许你编写灵活且可重用的代码,这些代码可以工作于多种类型的数据上。