前言:TypeScript中的泛型(Generics)是一种在函数、类、接口中使用类型变量的技术。通过泛型,可以在不确定具体类型的情况下,使用常规的函数、类、接口等类型定义进行开发。
以函数为例,下面是一个传统的JavaScript函数:
function identity(arg) {
return arg;
}
这个函数可以接收任何类型的参数,并返回相同类型的结果。但是,如果要保证函数的输入和输出类型相同,以避免一些潜在的错误,可以使用泛型来改进:
function identity<T>(arg: T): T {
return arg;
}
在这个例子中,函数名后面的表示类型变量,它可以表示任何类型。接着,函数的参数也使用了这个类型变量。最后,函数的返回值类型也指定为类型变量T。
当调用这个函数时,可以在函数名的后面使用尖括号(<>)来指定具体的类型:
let output = identity<string>("hello world");
这样,将会得到一个字符串类型。
泛型还可以在类和接口中使用。以接口为例,下面是一个传统的JavaScript对象:
function printBox(box) {
console.log(`Box width: ${box.width}, height: ${box.height}`);
}
let myBox = { width: 10, height: 20 };
printBox(myBox);
这个函数接收一个具有width和height属性的对象,输出这些属性的值。但是,如果要保证输入的对象具有这些属性,可以使用泛型来改进:
interface Box {
width: number;
height: number;
}
function printBox<T extends Box>(box: T) {
console.log(`Box width: ${box.width}, height: ${box.height}`);
}
let myBox = { width: 10, height: 20 };
printBox(myBox);
在这个例子中,Box是一个接口,它规定了width和height属性的类型。接着,在泛型函数中,使用了T extends Box来表示T必须是一个符合Box接口的类型。最后,调用函数时,传入的对象必须具有这些属性。
以类为例:
class Container<T> {
private items: T[] = [];
addItem(item: T) {
this.items.push(item);
}
getItem(index: number): T {
return this.items[index];
}
}
let container = new Container<number>();
container.addItem(1);
container.addItem(2);
container.addItem(3);
let firstItem = container.getItem(0);
在这个例子中,我们使用了类容器来存储元素,元素的类型通过类型参数 “” 指定。我们可以使用数字类型作为类型参数,并向容器添加数字。当我们从容器中获取元素时,typescript会根据容器定义的类型参数来推断元素类型。
总之,泛型是一种强大的类型抽象技术,可以让代码更加健壮和复用。在TypeScript中,泛型可以应用于函数、类、接口等多种类型定义中,极大地增强了代码的灵活性和可扩展性。