泛型(Generics)是 TypeScript 中的一种强大工具,用于构建可重用的组件。通过使用泛型,可以创建可以处理任意类型的函数、类和接口,而不必在定义时锁定具体类型。
泛型函数
定义泛型函数时,可以在函数名后面的尖括号 <T> 中指定一个或多个类型变量。
function identity<T>(arg: T): T {
return arg;
}
let output1 = identity<string>("Hello World");
let output2 = identity<number>(100);
console.log(output1); // "Hello World"
console.log(output2); // 100
TypeScript 可以根据传入的参数自动推断类型,因此可以省略类型参数:
let output3 = identity("Hello TypeScript"); // 类型推断为 string
泛型接口
可以使用泛型定义接口,以便接口中的属性和方法都可以使用这个泛型类型。
interface GenericIdentityFn<T> {
(arg: T): T;
}
function identity<T>(arg: T): T {
return arg;
}
let myIdentity: GenericIdentityFn<number> = identity;
console.log(myIdentity(123)); // 123
泛型类
类也可以使用泛型来创建灵活的和可重用的组件。
class GenericNumber<T> {
zeroValue: T;
add: (x: T, y: T) => T;
constructor(zeroValue: T, addFunction: (x: T, y: T) => T) {
this.zeroValue = zeroValue;
this.add = addFunction;
}
}
let myGenericNumber = new GenericNumber<number>(0, (x, y) => x + y);
console.log(myGenericNumber.add(5, 10)); // 15
泛型约束(Constraints)
有时需要对泛型类型进行约束,使其符合某些条件。可以使用 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 }); // 10
在泛型中使用类型参数
可以在一个泛型类型中使用另一个类型参数。
function getProperty<T, K extends keyof T>(obj: T, key: K) {
return obj[key];
}
let x = { a: 1, b: 2, c: 3, d: 4 };
console.log(getProperty(x, "a")); // 1
// console.log(getProperty(x, "m")); // 错误:类型“'m'”不满足约束“'a' | 'b' | 'c' | 'd'”。
泛型默认值
可以为泛型类型参数指定默认类型。
function createArray<T = string>(length: number, value: T): T[] {
let result: T[] = [];
for (let i = 0; i < length; i++) {
result[i] = value;
}
return result;
}
let stringArray = createArray(3, "hello"); // 默认类型 string
console.log(stringArray); // ["hello", "hello", "hello"]
let numberArray = createArray<number>(3, 42); // 指定类型 number
console.log(numberArray); // [42, 42, 42]
泛型工具类型
TypeScript 提供了一些内置的工具类型,例如 Partial、Readonly、Record 等,来帮助处理泛型。
interface Person {
name: string;
age: number;
}
// Partial 将所有属性变为可选
type PartialPerson = Partial<Person>;
// Readonly 将所有属性变为只读
type ReadonlyPerson = Readonly<Person>;
// Record 创建一个具有指定键和类型的对象类型
type StringDictionary = Record<string, number>;
泛型提供了一种灵活且类型安全的方式来构建可重用的代码组件,使得代码更加通用和易维护。在 TypeScript 中,泛型广泛用于函数、类、接口和工具类型,极大地增强了 TypeScript 的表达能力。