TypeScript笔记-泛型

120 阅读2分钟

系列文章

泛型

在组件化过程中,我们需要保证组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型,为组件提供了灵活性。

可以使用泛型来创建可重用的组件,一个组件可以支持多种类型的数据。这样用户就可以以自己的数据类型来使用组件。

设置一个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