1 什么是泛型
泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。 泛型使用<T> 来定义类型,<T> 中的T可以是U也可以是其他合法的字母,建议大写。泛型可以理解为不确定单独类型,函数中使用泛型,可以约束函数的参数和返回值类型相同。
2 泛型方法
当定义identity函数时,这个函数会返回任何传入它的值,不用泛型的话,这个函数可能是下面这样:
function identity(arg: number): number {
return arg;
}
但是这样的话,参数和返回值规定了必须为number类型。如果我们不确定它们的类型,要怎么写呢,我们可能会使用any类型来定义函数:
function identity(arg: any): any {
return arg;
}
但是使用any类型会导致这个函数可以接收任何类型的arg参数,这样就丢失了一些信息:传入的类型与返回的类型应该是相同的。如果我们传入一个数字,任何类型的值都有可能被返回。
对于这个问题,我们就可以使用类型变量来解决。类型变量是一种特殊的变量,只用于表示类型而不是值。它的语法格式为:
function 函数名<T>(参数: T): T {
return 值;
}
示例代码:
function identity<T>(arg: T): T {
return arg;
}
给identity添加了类型变量T。 T帮助我们捕获用户传入的类型(比如:number),之后我们就可以使用这个类型。 之后我们再次使用了 T当做返回值类型。现在我们可以知道参数类型与返回值类型是相同的了。 这允许我们跟踪函数里使用的类型的信息。
定义了泛型方法后,可以用两种方法使用。
var a = identity<string>("myString");
var a = identity("myString");
3 泛型类
当我们需要实现找最小数的算法时,并且需要同时支持返回数字和字符串两种类型,就可以通过类的泛型来实现。
示例代码: 非泛型实现方式
class MinClass {
list: number[] = [];
add(num: number) {
this.list.push(num);
}
min(): number {
var minNum = this.list[0];
for (var i = 0; i < this.list.length; i++) {
if (minNum > this.list[i]) {
minNum = this.list[i];
}
}
return minNum;
}
}
示例代码:泛型方式实现
class MinClass<T> {
list: T[] = [];
add(num: T) {
this.list.push(num);
}
min(): T {
var minNum = this.list[0];
for (var i = 0; i < this.list.length; i++) {
if (minNum > this.list[i]) {
minNum = this.list[i];
}
}
return minNum;
}
}
4 泛型接口
首先来看一下普通函数接口:
interface ConfigFn {
(value1: string, value2: string): string;
}
那么如果将它转换成泛型接口呢?有下面两种方法:
1、第一种定义方式
interface ConfigFn {
<T>(value: T): T;
}
2、第二种方式
interface ConfigFn<T> {
(value: T): T;
}
|