系列文章
泛型
在组件化过程中,我们需要保证组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型,为组件提供了灵活性。
可以使用泛型来创建可重用的组件,一个组件可以支持多种类型的数据。这样用户就可以以自己的数据类型来使用组件。
设置一个identity函数,这个函数会返回任何传入它的值。
function identity(arg: any): any {
return arg;
}
// 缺点:传参和返回值类型为any,导致传入和返回值类型可能不一致
正确的写法,使用“类型变量”
function identity<T>(arg: T): T {
return arg;
}
// 此即为泛型
类型变量
类型变量——代表任意类型
通过“类型变量”,我们可以获取用户传入的类型,并使用到后续操作中。
上例中,我们给identity函数添加了类型变量 T,T 帮助我们捕获用户传入的参数类型,之后就可以在放回值中使用这个类型。
泛型函数:
function identity<T>(arg: T): T {
return arg;
}
let myIdentity: {<T>(arg: T): T} = identity;
泛型接口
interface GenericIdentityFn<T> {
(arg: T): T
}
function identity<T>(arg: T): T {
return arg;
}
let myIdentity: GenericIdentityFn<number> = identity;
泛型类
泛型类指的是类的实例部分,类的静态属性不能使用这个泛型类型。
class GenericNumber<T> {
zeroValue: T;
add: (x: T, y: T) => T;
}
let myGenericNumber = new GenericNumber<number>();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = function(x, y) { return x + y; };
泛型约束
以下示例将提示错误,因为编译器不能证明每种类型都有length属性。
function identity<T>(arg: T): T {
return arg.length; // error
}
通过设定一个接口,来约束泛型。即传入的参数需要包含该接口所设定的属性。
interface Lengthwise {
length: number
}
function loggingIdentity<T extends Lendthwise>(arg: T): T {
console.log(arg.length); // 不会报错,因为有length属性
return arg;
}
loggingIdentity(3); // Error, number doesn't have a .length property
loggingIdentity({length: 10, value: 3}); // OK