fe-interview
fe-interview copied to clipboard
[TypeScript] 第1546天 在TypeScript中如何定义和使用泛型?
在 TypeScript 中,泛型(Generics)是一种强大的工具,它允许你创建可重用的组件,这些组件不仅可以适用于一种数据类型,还可以适用于多种数据类型。使用泛型可以在编写代码时更灵活,同时保持类型安全。以下是定义和使用泛型的方法和示例:
1. 泛型函数
定义一个泛型函数,使用尖括号 <> 来指定泛型参数。
示例
function identity<T>(arg: T): T {
return arg;
}
let output1 = identity<string>("myString"); // 明确指定类型
let output2 = identity<number>(42); // 明确指定类型
// TypeScript 可以根据传入的参数自动推断类型
let output3 = identity("myString");
let output4 = identity(42);
console.log(output1); // 输出: myString
console.log(output2); // 输出: 42
2. 泛型接口
可以使用泛型来定义接口,使得接口中的属性和方法可以使用多种类型。
示例
interface GenericIdentityFn<T> {
(arg: T): T;
}
function identity<T>(arg: T): T {
return arg;
}
let myIdentity: GenericIdentityFn<number> = identity;
console.log(myIdentity(42)); // 输出: 42
3. 泛型类
定义一个泛型类,使类的属性和方法可以使用多种类型。
示例
class GenericNumber<T> {
zeroValue: T;
add: (x: T, y: T) => T;
}
let myGenericNumber = new GenericNumber<number>();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = function(x, y) { return x + y; };
console.log(myGenericNumber.add(10, 20)); // 输出: 30
4. 泛型约束
有时候你可能希望对泛型类型进行约束,使其满足某些条件。可以使用接口来实现泛型约束。
示例
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 });
5. 使用多个类型参数
你可以在泛型中使用多个类型参数,以实现更复杂的类型关系。
示例
function swap<T, U>(tuple: [T, U]): [U, T] {
return [tuple[1], tuple[0]];
}
let swapped = swap([7, "seven"]);
console.log(swapped); // 输出: ["seven", 7]
6. 泛型工具类型
TypeScript 提供了一些常用的泛型工具类型,如 Partial<T>、Readonly<T>、Record<K, T> 等,用于处理常见的类型转换和操作。
示例
interface Person {
name: string;
age: number;
}
let partialPerson: Partial<Person> = {};
partialPerson.name = "John"; // 允许,只要 name 是 string 类型
partialPerson.age = 30; // 允许,只要 age 是 number 类型
let readonlyPerson: Readonly<Person> = {
name: "John",
age: 30
};
// readonlyPerson.age = 31; // 错误:不能修改只读属性
总结
泛型使得 TypeScript 代码更加灵活和可重用,同时保持类型安全。通过使用泛型函数、泛型接口、泛型类和泛型工具类型,你可以在编写代码时处理多种类型,而不需要牺牲类型检查和代码提示的优势。这使得代码不仅更具适应性,还可以减少重复代码,提高代码质量。