本章将学习在TypeScript中如何使用泛型,泛型是TypeScript很 重要 的东西。在实际项目中有很多地方用到了泛型 。
TS中的泛型(Generics)是一种在函数、类和接口中使用参数化类型的方式。它允许我们在定义和使用时指定类型,从而增加代码的灵活性和可重用性。通过使用泛型,我们可以编写通用的数据结构和算法,使代码更加抽象和可扩展。
在没学泛型之前 我们定义函数时 只能定义固定值 或者干脆直接用any,那么当我们想要可以传进去不同的类型,且传进去什么类型就返回什么类型 就行不通了 ,所以泛型就可以解决此问题
//没学泛型之前的写法
function identity<string>(arg: string): string {
return arg;
}
泛型在定义函数、类或接口时,使用尖括号 <> 来声明泛型,并在使用时传入具体的类型。
function identity<T>(arg: T): T {
return arg;
}
//使用的时候我们定义了string 就代表
//里面的 所有T 都为string 类型
let output = identity<string>("hello");
console.log(output); // hello
在泛型函数或类中,我们可以使用泛型变量来表示任意类型。泛型变量可以用于函数的参数、返回值、属性等地方。
function identity<T>(arg: T): T {
return arg;
}
function loggingIdentity<T>(arg: T[]): T[] {
console.log(arg.length);
return arg;
}
let output = loggingIdentity<string>(["apple", "banana", "orange"]);
console.log(output); // ["apple", "banana", "orange"]
我们还可以使用泛型来定义类型,这样我们就可以创建符合特定泛型类型约束的实例。
例如我们之前学过的接口的定义 定义一个全是字符串类型的接口,可以用下面的写法,看不懂的同学可以回去看一下 ts进阶类型篇
interface GenericIdentityFn{
[arr:string]:string
}
但我们如果想要一个接口值是string类型的 又想要一个number类型 的是不是要定义很多个。而有了泛型我们就能定义一个接口解决问题
//这里就是上面代码演化而来
interface GenericIdentityFn<T> {
(arg: T): T;
}
function identity<T>(arg: T): T {
return arg;
}
//在使用的时候我们可以传如number 也可以传入string
let myIdentity: GenericIdentityFn<number> = identity;
在类的使用中 我们也可以结合泛型优化代码,使用方法跟函数类似名称后面定义<类型>。
class Box<T> {
private value: T;
constructor(value: T) {
this.value = value;
}
getValue(): T {
return this.value;
}
setValue(value: T): void {
this.value = value;
}
}
// 使用泛型类
const stringBox = new Box<string>("Hello");
console.log(stringBox.getValue()); // 输出 "Hello"
stringBox.setValue("World");
console.log(stringBox.getValue()); // 输出 "World"
const numberBox = new Box<number>(42);
console.log(numberBox.getValue()); // 输出 42
numberBox.setValue(100);
console.log(numberBox.getValue()); // 输出 100
TypeScript 泛型的使用场景有很多,以下是一些常见的场景:
提供对不同类型的支持:泛型可以在函数、类和接口中声明类型变量,使得这些函数、类和接口可以适用于不同类型的数据。例如,一个通用的数组排序函数可以使用泛型来支持不同类型的数组排序。
增强代码的可读性和可维护性:使用泛型可以提高代码的可读性和可维护性,因为它能够明确地表达代码的意图。使用泛型可以在编译阶段捕获一些类型错误,减少运行时错误的发生。
减少代码重复:使用泛型可以减少代码的重复,提高代码的复用性。通过使用泛型,可以编写一次代码来处理多种类型的数据,而不需要为每种类型编写重复的代码。
实现抽象数据结构:泛型可以用于实现抽象数据结构,如栈、队列和链表等。通过使用泛型,可以在编译阶段进行类型检查,确保数据的正确性。
扩展现有的类型系统:TypeScript的类型系统是静态类型的,但是有时候需要处理一些动态类型的数据。使用泛型可以在静态类型系统中引入一些动态类型的概念,从而提供更灵活的类型检查。