[TypeScript][文档]泛型
——泛型是一种类型变量,只用于表示类型而不是值。用于让用户传入类型。
function identity<T>(arg: T): T { return arg; }
可以用两种方式使用:
let output = identity<string>("myString"); // type of output will be 'string' //这里我们明确的指定了T是string类型,并做为一个参数传给函数,使用了<>括起来而不是()。 //第二种方法更普遍。利用了类型推论 -- 即编译器会根据传入的参数自动地帮助我们确定T的类型: let output = identity("myString"); // type of output will be 'string'
一、泛型变量
在函数体中使用泛型变量要注意到:你必须把这些参数当做是任意或所有类型。——也就是说,只能使用所有类型都可用的操作
function loggingIdentity<T>(arg: T): T { // 使用这个函数的人可能传入的是个数字,而数字是没有 .length
属性的
console.log(arg.length); // Error: T doesn't have .length
return arg;
}
假设传入的时数组,就可以这样操作:
function loggingIdentity<T>(arg: Array<T>): Array<T> { console.log(arg.length); // Array has a .length, so no more error return arg; }
二、泛型函数的类型(泛型接口)
function identity<T>(arg: T): T { return arg; } let myIdentity: <T>(arg: T) => T = identity; // 我们也可以使用不同的泛型参数名,只要在数量上和使用方式上能对应上就可以。 let myIdentity: <U>(arg: U) => U = identity; //我们还可以使用带有调用签名的对象字面量来定义泛型函数: let myIdentity: {<T>(arg: T): T} = identity; // 这有点类似于接口的写法了
泛型接口的写法如下:
interface GenericIdentityFn { <T>(arg: T): T; } function identity<T>(arg: T): T { return arg; } let myIdentity: GenericIdentityFn = 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; };
四、泛型约束
泛型本身指代任何类型,但是这样就很难兼顾一些操作,因此,我们给泛型加上一些约束,这样可使用的类型范围少了,但是操作也方便一些。
interface Lengthwise { length: number; } function loggingIdentity<T extends Lengthwise>(arg: T): T { console.log(arg.length); // Now we know it has a .length property, so no more error return arg; }
现在这个泛型函数被定义了约束,因此它不再是适用于任意类型:
loggingIdentity(3); // Error, number doesn't have a .length property
我们需要传入符合约束类型的值,必须包含必须的属性:
loggingIdentity({length: 10, value: 3});