TypeScript 泛型学习指南
泛型是TypeScript中非常重要的概念,它允许我们创建可重用的组件,这些组件可以支持多种类型而不只是一个单一类型。
# 1. 基本泛型示例
# 泛型函数
// 普通函数只能返回一种特定类型
function identity(arg: number): number {
return arg;
}
// 使用泛型,可以适用于多种类型
function identityGeneric<T>(arg: T): T {
return arg;
}
// 使用
let output1 = identityGeneric<string>("myString"); // 类型为string
let output2 = identityGeneric<number>(100); // 类型为number
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
# 泛型自动类型推断
// TypeScript可以自动推断泛型类型
let output3 = identityGeneric("myString"); // 类型推断为string
let output4 = identityGeneric(100); // 类型推断为number
1
2
3
2
3
# 2. 泛型数组示例
// 处理数组的泛型函数
function loggingIdentity<T>(arg: T[]): T[] {
console.log(arg.length); // 数组有length属性
return arg;
}
// 或者可以这样写
function loggingIdentity2<T>(arg: Array<T>): Array<T> {
console.log(arg.length);
return arg;
}
// 使用
let arr1 = loggingIdentity([1, 2, 3]); // T被推断为number
let arr2 = loggingIdentity(["a", "b", "c"]); // T被推断为string
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 3. 泛型接口
// 定义泛型接口
interface GenericIdentityFn<T> {
(arg: T): T;
}
// 使用
function identity<T>(arg: T): T {
return arg;
}
let myIdentity: GenericIdentityFn<number> = identity;
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# 4. 泛型类
class GenericNumber<T> {
zeroValue: T;
add: (x: T, y: T) => T;
}
// 使用number类型
let myGenericNumber = new GenericNumber<number>();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = (x, y) => x + y;
// 使用string类型
let stringNumeric = new GenericNumber<string>();
stringNumeric.zeroValue = "";
stringNumeric.add = (x, y) => x + y;
console.log(stringNumeric.add("Hello ", "World")); // 输出 "Hello World"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 5. 泛型约束
有时候我们需要限制泛型的类型范围。
interface Lengthwise {
length: number;
}
// 使用extends约束泛型T必须包含length属性
function loggingIdentityWithConstraint<T extends Lengthwise>(arg: T): T {
console.log(arg.length);
return arg;
}
// 正确使用
loggingIdentityWithConstraint({length: 10, value: 3});
loggingIdentityWithConstraint("hello"); // string有length属性
// 错误使用
// loggingIdentityWithConstraint(3); // 数字没有length属性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 6. 在泛型约束中使用类型参数
function getProperty<T, K extends keyof T>(obj: T, key: K) {
return obj[key];
}
let x = { a: 1, b: 2, c: 3, d: 4 };
getProperty(x, "a"); // 正确
// getProperty(x, "m"); // 错误: 'm'不在x的key中
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 7. 泛型与默认类型
interface MyGenericInterface<T = string> {
value: T;
}
// 不指定类型参数,使用默认string
let obj1: MyGenericInterface = { value: "hello" };
// 明确指定类型
let obj2: MyGenericInterface<number> = { value: 123 };
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 8. 实用示例:数据响应包装
interface ApiResponse<T> {
success: boolean;
data?: T;
error?: string;
}
function fetchUser(): ApiResponse<{name: string, age: number}> {
// 模拟API调用
return {
success: true,
data: {name: "Alice", age: 30}
};
}
function fetchProducts(): ApiResponse<Array<{id: number, name: string, price: number}>> {
// 模拟API调用
return {
success: true,
data: [
{id: 1, name: "Laptop", price: 999},
{id: 2, name: "Phone", price: 699}
]
};
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
通过这些例子,你应该对TypeScript泛型有了基本的理解。泛型的主要优势是:
- 提高代码复用性
- 提供更好的类型检查
- 减少使用any类型,保持类型安全