TypeScript 泛型详解
在 TypeScript 中,泛型(Generics)是一种在定义函数、接口或类时创建可重用组件的方式,这些组件能够工作于多种数据类型。泛型允许你编写灵活且可重用的代码,而无需为了适配不同的数据类型去编写重复的代码。
- 泛型函数
- 泛型函数是在调用时指定其类型参数的函数。
- 示例:泛型身份函数
function identity<T>(arg: T): T {
return arg;
}
let output1 = identity<string>("myString"); // output1 的类型是 string
let output2 = identity<number>(123); // output2 的类型是 number
let output3 = identity(true); // 类型会被自动推断为 boolean
在上面的例子中,T
是一个类型变量,用于表示任何类型。在调用 identity
函数时,你可以传入任何类型的参数,T
将会变为该参数的类型。
- 泛型类
泛型类是在类定义时有类型参数的类。
示例:泛型类
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;
}
zero(): T {
return this.zeroValue;
}
addTogether(x: T, y: T): T {
return this.add(x, y);
}
}
let myGenericNumber = new GenericNumber<number>(0, (x, y) => x + y);
console.log(myGenericNumber.zero()); // 输出 0
console.log(myGenericNumber.addTogether(1, 2)); // 输出 3
在这个例子中,GenericNumber<T>
类有一个类型参数 T
,用于指定 zeroValue 的类型以及 add
方法的参数和返回值的类型。
- 泛型接口
泛型接口与泛型类类似,不过它是用来定义对象的形状。
示例:泛型接口
interface GenericIdentityFn<T> {
(arg: T): T;
}
function identity<T>(arg: T): T {
return arg;
}
let myIdentity: GenericIdentityFn<number> = identity;
在这个例子中,GenericIdentityFn<T>
接口定义了一个接收 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 属性
在这个例子中,我们创建了一个泛型接口 Lengthwise
,它要求任何实现该接口的对象都必须有一个 length
属性。然后,我们定义了一个泛型函数 loggingIdentity
,它接受一个类型为 T 的参数,但是 T 必须实现了 Lengthwise
接口。
-
泛型与数组
泛型在数组操作中非常有用,特别是当你不知道数组元素的确切类型时。
示例:泛型数组函数
function reverse<T>(items: T[]): T[] {
let reversedItems = items.slice().reverse();
return reversedItems;
}
let reversedNumbers = reverse([1, 2, 3, 4]);
console.log(reversedNumbers); // 输出 [4, 3, 2, 1]
在这个例子中,reverse 函数接受一个类型为 T[] 的数组,并返回一个新的反转后的数组,其类型也是 T[]
。
-
泛型默认值
从 TypeScript 2.3 开始,你可以为泛型参数提供默认值。
示例:泛型默认值
function createArray<T = number>(length: number, value: T = 0): T[] {}