TypeScript 泛型接口
泛型是TypeScript中一个强大的特性,它允许我们编写灵活且可重用的代码。泛型接口是泛型的一种应用,它允许我们在接口中使用类型参数,从而使接口更加通用。本文将详细介绍TypeScript中的泛型接口,并通过示例展示其实际应用。
什么是泛型接口?
泛型接口是一种可以接受类型参数的接口。通过使用泛型接口,我们可以定义一个通用的接口,该接口可以适用于多种类型,而不需要为每种类型都定义一个单独的接口。
基本语法
泛型接口的定义与普通接口类似,只是在接口名称后面添加了类型参数。例如:
interface GenericIdentityFn<T> {
(arg: T): T;
}
在这个例子中,GenericIdentityFn
是一个泛型接口,它接受一个类型参数 T
。这个接口定义了一个函数类型,该函数接受一个类型为 T
的参数,并返回一个类型为 T
的值。
使用泛型接口
示例1:简单的泛型接口
让我们从一个简单的例子开始。假设我们有一个接口 Box
,它表示一个包含任意类型值的盒子。我们可以使用泛型接口来定义这个盒子:
interface Box<T> {
value: T;
}
let numberBox: Box<number> = { value: 42 };
let stringBox: Box<string> = { value: "Hello" };
console.log(numberBox.value); // 输出: 42
console.log(stringBox.value); // 输出: Hello
在这个例子中,Box
是一个泛型接口,它接受一个类型参数 T
。我们可以通过指定不同的类型参数来创建不同类型的盒子。
示例2:泛型函数接口
泛型接口也可以用于定义函数类型。例如,我们可以定义一个泛型接口 Mapper
,它表示一个将输入类型 T
映射到输出类型 U
的函数:
interface Mapper<T, U> {
(input: T): U;
}
let numberToString: Mapper<number, string> = (num) => num.toString();
console.log(numberToString(42)); // 输出: "42"
在这个例子中,Mapper
是一个泛型接口,它接受两个类型参数 T
和 U
。我们可以通过指定不同的类型参数来创建不同类型的映射函数。
实际应用场景
案例1:API响应处理
在实际开发中,我们经常需要处理来自API的响应。假设我们有一个API返回一个包含数据的响应,我们可以使用泛型接口来定义这个响应的结构:
interface ApiResponse<T> {
status: number;
data: T;
}
interface User {
id: number;
name: string;
}
let userResponse: ApiResponse<User> = {
status: 200,
data: { id: 1, name: "John Doe" }
};
console.log(userResponse.data.name); // 输出: John Doe
在这个例子中,ApiResponse
是一个泛型接口,它接受一个类型参数 T
,表示响应的数据类型。我们可以通过指定不同的类型参数来处理不同类型的API响应。
案例2:集合类
泛型接口还可以用于定义集合类。例如,我们可以定义一个泛型接口 Collection
,它表示一个包含任意类型元素的集合:
interface Collection<T> {
items: T[];
add(item: T): void;
get(index: number): T;
}
class NumberCollection implements Collection<number> {
items: number[] = [];
add(item: number): void {
this.items.push(item);
}
get(index: number): number {
return this.items[index];
}
}
let numbers = new NumberCollection();
numbers.add(1);
numbers.add(2);
console.log(numbers.get(0)); // 输出: 1
在这个例子中,Collection
是一个泛型接口,它接受一个类型参数 T
,表示集合中的元素类型。我们可以通过实现这个接口来创建不同类型的集合类。
总结
泛型接口是TypeScript中一个非常有用的工具,它允许我们定义通用的接口,从而编写更加灵活和可重用的代码。通过使用泛型接口,我们可以避免为每种类型都定义一个单独的接口,从而提高代码的可维护性和可扩展性。
在实际开发中,泛型接口可以应用于多种场景,如API响应处理、集合类等。通过掌握泛型接口的使用,我们可以更好地利用TypeScript的类型系统,编写出更加健壮和高效的代码。
附加资源与练习
- TypeScript官方文档: Generics
- 练习: 尝试定义一个泛型接口
Pair<T, U>
,它表示一个包含两个元素的元组,并实现一个函数swap
,用于交换元组中的两个元素。
interface Pair<T, U> {
first: T;
second: U;
}
function swap<T, U>(pair: Pair<T, U>): Pair<U, T> {
return { first: pair.second, second: pair.first };
}
let pair: Pair<number, string> = { first: 1, second: "hello" };
let swappedPair = swap(pair);
console.log(swappedPair); // 输出: { first: "hello", second: 1 }
通过完成这些练习,你将更深入地理解泛型接口的使用,并能够在实际项目中灵活应用它们。