在 TypeScript 中,泛型(Generics)泛型是一种用于创建可以用于多个不同类型的参数化定义的机制,以在多个地方重用相同的代码片段来处理不同类型的数据。。它允许我们在定义函数、类或接口时使用参数来表示类型,并在实际使用时确定具体的类型。
- 准备工作
- 安装[Node.js] node -v
- 安装[Node Package Manager]
- 安装TypeScript npm install -g typescript
-
TypeScript里的泛型是什么?
- 在 TypeScript 中,泛型(Generics)是一种用于创建可重用代码的强大工具。它允许我们在编写函数、类和接口时使用参数化类型,以处理多种类型的数据,同时保持类型安全性。 泛型的主要目的是在编译时期提供更严格的类型检查,并提供可重用的代码模板。通过使用泛型,我们可以写出更通用、灵活且类型安全的代码,以适应不同类型数据的操作和处理需求。
-
在VS Code中配置TypeScript
- 在 TypeScript 中,我们可以在函数、类和接口的定义中使用泛型。
- 下面是 TypeScript 中泛型的常见使用方法和场景:
- 泛型函数(Generic Functions):泛型函数可以在函数声明或函数表达式中定义泛型参数,以处理不同类型的输入参数和返回值。在函数名之后使用尖括号 来定义泛型参数,例如 function identity(arg: T): T。在函数体内部,可以使用泛型参数 T 来操作参数和返回值的类型。使用泛型函数时,可以在调用时明确指定具体的类型,也可以让 TypeScript 推断出类型。
function identity<T>(arg: T): T {
return arg;
}
let result = identity<string>("Hello");
// result 的类型为 string
typescript复制代码
- 泛型约束可以限制泛型类型,以满足特定条件。通过使用 extends 关键字和一个接口或类来约束泛型类型。例如,function loggingIdentity(arg: T): T 中的 约束了传入的参数 arg 必须具有 length 属性。这样做可以确保在函数内部安全地访问 arg.length,避免类型错误的运行时问题。
interface Lengthwise {
length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T {
console.log(arg.length);
return arg;
}
let result = loggingIdentity("Hello");
// result 的类型为 string
在上述示例中,loggingIdentity 函数使用了一个泛型约束,要求传入的参数 arg 必须具有 length 属性。这样一来,我们就可以在函数内部安全地访问 arg.length,而无需担心类型错误导致的运行时问题。
- 泛型类:泛型类可以创建支持不同类型的通用数据结构或算法。通过在类名后面使用尖括号 来定义泛型参数,并在类的属性和方法中使用泛型参数。例如,class DataStore 中的 T 表示存储的数据类型。通过指定具体的类型来实例化泛型类,例如 let store = new DataStore()。这样就创建了一个用于存储数字类型数据的实例。可以在泛型类中定义各种操作和方法,以适应不同类型的数据。
class DataStore<T> {
private data: T[];
constructor() {
this.data = [];
}
addItem(item: T) {
this.data.push(item);
}
getItems(): T[] {
return this.data;
}
}
let store = new DataStore<number>();
store.addItem(1);
store.addItem(2);
let items = store.getItems();
// items 的类型为 number[]
在上述示例中,我们创建了一个存储不同类型数据的泛型类 DataStore。我们通过在实例化类时指定 T 的具体类型为 number,从而创建了一个用于存储数字类型数据的实例 store。我们还可以通过调用 addItem 方法来添加数字数据,通过 getItems 方法来获取存储的数字数组。
- 泛型接口:可以在接口定义时使用泛型,以创建更通用的接口定义。通过在接口名后面使用尖括号 定义泛型参数,并在接口的方法和属性中使用泛型参数。例如,interface Repository中的 T 表示具体的存储对象类型。可以使用泛型接口来定义操作和处理不同类型数据的通用方法和约束。
interface Repository<T> {
getById(id: string): T | undefined;
save(item: T): void;
}
interface User {
id: string;
name: string;
}
class UserRepository implements Repository<User> {
private users: User[] = [];
getById(id: string): User | undefined {
return this.users.find(user => user.id === id);
}
save(user: User): void {
this.users.push(user);
}
}
在这个例子中,我们定义了一个通用的 Repository 接口,并使用泛型 T 表示具体的存储对象类型。然后,我们实现了 UserRepository 类,将 User 类型作为泛型参数。这样就可以创建一个用于操作 User 对象的存储库。
-
举例:
例如,如果要在 TypeScript 中创建一个泛型函数来处理不同类型的position对象,可以使用以下方式:
function processData<T>(data: T): void {
// 处理数据的逻辑
}
typescript复制代码
然后,可以通过以下方式调用泛型函数,并提供具体的 position 对象类型:
let position: { isShow: boolean; place: string } = {
isShow: true,
place: "London",
};
processData(position);
typescript复制代码
这样,processData 函数就可以接收任何类型的对象作为参数进行处理,而不仅限于 position 对象。
这些只是 TypeScript 中泛型的一些常见使用方法和场景,泛型的应用可以更加复杂和灵活。泛型在处理可重用和类型安全的代码方面非常有用,可以大大简化开发工作并提高代码质量。