概论
为什么要使用泛型
创建可重用的组件,一个组件可以支持多种类型的数据。
泛型理解
Generics - Types which take parameters 相当于传入到function | interface | class中一个参数
泛型使用
基础定义
- 有一个类型参数在最前面,像函数声明一样 元素形式:
//demo1
function identity<Type>(arg: Type): Type {
return arg;
}
//泛型参数名可自己定义,下面示例与上面等同
function identity<T>(arg: T): T {
return arg;
}
数组形式:
//demo2
function loggingIdentity<Type>(arg: Type[]): Type[] {
console.log(arg.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;
}
- 可以使用不同的泛型参数名,如demo1所示
- 可以使用带有调用签名的对象字面量来定义泛型函数,如demo3中
{<T>(arg: T): T}
//demo4
function identity<T>(arg: T): T {
return arg;
}
let myIdentity: {<T>(arg: T): T} = identity;
泛型接口 Generic Interface
在demo4的例子中,将带有调用签名的对象字面量提取成接口
//demo5
interface GenericIdentityFn {
<T>(arg: T): T; //函数形式接口,传入参数arg,返回同类型值
}
function identity<T>(arg: T): T {
return arg;
}
let myIdentity: GenericIdentityFn = identity;
如果把泛型参数当做interface的一个参数,则:
//demo6
interface GenericIdentityFn<T> {
(arg: T): T;
}
function identity<T>(arg: T): T {
return arg;
}
let myIdentity: GenericIdentityFn<number> = identity;
泛型类 Generic Classes
同泛型接口差不多。 泛型类使用( <>)括起泛型类型,跟在类名后面
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; };
泛型约束 Generic Constraints
- 普通泛型约束
把将要传入的泛型,继承自某个interface | class,对泛型进行约束,如:
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}); // Now we know it has a .length property, so no more error
- 在泛型约束中使用类型参数
如下demo所示:通过keyof的解析实现对K的约束限制(keyof的理解可参见下一篇)
function getProperty<T, K extends keyof T>(obj: T, key: K) {
console.log(obj[key]);
return obj[key];
}
let x = { a: 1, b: 2, c: 3, d: 4 };
getProperty(x, "a");
getProperty(x, "m"); //Argument of type '"m"' is not assignable to parameter of type '"a" | "b" | "c" | "d"'.
泛型中使用类类型(Using Class Types in Generics)
{ new (): Type }其构造函数返回值是泛型Type
function create<Type>(c: { new (): Type }): Type {
return new c();
}
如下demo所示:对c: new () => A的理解
class BeeKeeper {
hasMask: boolean = true;
}
class ZooKeeper {
nametag: string = "Mikle";
}
class Animal {
numLegs: number = 4;
}
class Bee extends Animal {
keeper: BeeKeeper = new BeeKeeper();
}
class Lion extends Animal {
keeper: ZooKeeper = new ZooKeeper();
}
/**
传入的泛型是:A extends Animal
对"c: new () => A"理解:
createInstance参数c必须是这样的一个类:
其构造函数返回值是传入的泛型A
*/
function createInstance<A extends Animal>(c: new () => A): A {
return new c();
}
createInstance(Animal).numLegs; //4
createInstance(Lion).keeper.nametag; //Mikle
createInstance(Bee).keeper.hasMask; //true