TypeScript中的泛型
本文将解释TypeScript中的泛型。
YouTube Video
TypeScript中的泛型
TypeScript中的泛型是一项功能,通过参数化类型,可以定义可重用且类型安全的函数、类和接口。使用泛型可以编写不依赖特定类型的代码,从而可以对各种类型执行相同的操作。
泛型基础
泛型类似于模板,可以接受类型作为参数,使函数和类能够处理不同的类型。
泛型函数
以下是一个使用泛型指定参数类型的函数示例。
1function identity<T>(value: T): T {
2 return value;
3}
4
5console.log(identity<number>(42)); // 42
6console.log(identity<string>("Hello")); // Hello
T是一个泛型类型参数,表示函数参数和返回值的类型。实际的类型在调用函数时确定。- 通过显式指定
<number>或<string>,您正在指定类型。
泛型类型在没有显式指定的情况下也能工作,因为TypeScript会进行类型推断。
1function identity<T>(value: T): T {
2 return value;
3}
4
5console.log(identity(42)); // 42
6console.log(identity("Hello")); // Hello
- 即使没有明确指定
<number>或<string>,类型推断也会发生。identity(42)被推断为number,而identity("Hello")被推断为string。
泛型约束
通过对泛型设置约束,可以将其限制为只接受特定的类型。
1function loggingIdentity<T extends { length: number }>(arg: T): T {
2 console.log(arg.length);
3 return arg;
4}
5
6loggingIdentity("Hello"); // 5
7loggingIdentity([1, 2, 3]); // 3
8
9// loggingIdentity(42); // Error: number does not have a length property.
- 指定
T extends { length: number }表示T必须是具有length属性的类型。因此,缺少length属性的类型将不会被接受。
keyof 的结合使用
将泛型与 keyof 结合使用,可以以类型安全的方式获取属性名。
1function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
2 return obj[key];
3}
4
5const person = { name: "Bob", age: 30 };
6const personName = getProperty(person, "name"); // string
7console.log(personName);
8
9// const error = getProperty(person, "unknown"); // Error
K受keyof T的约束,表示只能指定T中存在的键。指定不存在的键会导致编译错误。
泛型类
类也可以使用泛型定义。泛型类为属性和方法提供灵活的类型。
1class Box<T> {
2 private _value: T;
3
4 constructor(value: T) {
5 this._value = value;
6 }
7
8 public getValue(): T {
9 return this._value;
10 }
11
12 public setValue(value: T): void {
13 this._value = value;
14 }
15}
16
17const numberBox = new Box<number>(100);
18console.log(numberBox.getValue()); // 100
19
20const stringBox = new Box<string>("Hello");
21console.log(stringBox.getValue()); // Hello
Box<T>将类中使用的类型T声明为泛型。这样可以将同一个类重用于不同的类型。
泛型接口
泛型也可以与接口一起使用。
1interface Pair<T, U> {
2 first: T;
3 second: U;
4}
5
6const numberStringPair: Pair<number, string> = { first: 1, second: "One" };
7console.log(numberStringPair); // { first: 1, second: 'One' }
8
9const booleanArrayPair: Pair<boolean, number[]> = { first: true, second: [1, 2, 3] };
10console.log(booleanArrayPair); // { first: true, second: [ 1, 2, 3 ] }
- 通过使用
Pair<T, U>指定两个泛型类型,可以定义具有不同类型组合的对象。
默认类型参数
还可以为泛型类型参数指定默认类型。
1function createArray<T = string>(length: number, value: T): T[] {
2 return Array(length).fill(value);
3}
4
5console.log(createArray(3, "a")); // ['a', 'a', 'a']
6console.log(createArray(3, 100)); // [100, 100, 100]
- 我们通过使用
<T = string>将默认类型参数设置为string。如果没有显式指定类型,T将默认为string类型。
泛型类型别名
泛型也可以用作类型别名 (type)。
1type Result<T> = {
2 success: boolean;
3 data: T;
4};
5
6const successResult: Result<number> = { success: true, data: 42 };
7const errorResult: Result<string> = { success: false, data: "Error occurred" };
8
9console.log(successResult); // { success: true, data: 42 }
10console.log(errorResult); // { success: false, data: 'Error occurred' }
Result<T>表示一个包含类型为T的数据的结果对象。通过这种方式,可以使用泛型创建灵活的类型别名。
多种泛型类型
通过使用多种泛型类型,可以定义更加通用的函数和类。
1function merge<T, U>(obj1: T, obj2: U): T & U {
2 return { ...obj1, ...obj2 };
3}
4
5const person = { name: "Alice" };
6const job = { title: "Engineer" };
7
8const merged = merge(person, job);
9console.log(merged); // { name: 'Alice', title: 'Engineer' }
merge函数接收两种不同类型T和U,然后将它们组合并返回一个新对象。
总结
- 泛型 通过将类型作为参数,使代码可复用且类型安全。
- 通过在 函数、类和接口 中使用泛型,可以编写可以处理各种类型的灵活逻辑。
- 通过向类型参数添加 约束 或设置 默认类型参数,可以控制泛型的范围。
通过使用泛型,你可以编写与类型无关的通用代码,充分利用 TypeScript 强大的类型系统。
您可以在我们的YouTube频道上使用Visual Studio Code跟随上述文章进行学习。 请也查看我们的YouTube频道。