Generics 泛型
Generics 初探
ts
function identity(arg: number): number {
return arg;
}
function identity2(arg: any): any {
return arg;
}
// 泛型
function identity3<T>(arg: T): T {
return arg;
}
// 第一种:传入所有的参数,包括类型参数
identity3<string>('hello');
// 第二种:类型参数推断
identity3('worlds');使用泛型类型变量
ts
function identity4<Type>(arg: Type): Type {
console.log(arg.length); // Error: T doesn't have .length
return arg;
}
function identity5<Type>(arg: Type[]): Type[] {
console.log(arg.length); // No error, since arg is an array
return arg;
}
function identity6<Type>(arg: Array<Type>): Array<Type> {
console.log(arg.length); // No error, since arg is an array
return arg;
}泛型类型
泛型接口
ts
interface GenericIdentityFn {
<Type>(arg: Type): Type;
}
function identity<Type>(arg: Type): Type {
return arg;
}
let myIdentity: GenericIdentityFn = identity;将泛型参数作为整个接口的参数
ts
interface GenericIdentityFn<Type> {
(arg: Type): Type;
}
function identity<Type>(arg: Type): Type {
return arg;
}
let myIdentity: GenericIdentityFn<number> = identity;泛型类
与接口类似
ts
class GenericNumber<NumType> {
zeroValue: NumType;
add: (x: NumType, y: NumType) => NumType;
constructor() {}
// constructor(zeroValue: NumType, add: (x: NumType, y: NumType) => NumType) {
// this.zeroValue = zeroValue;
// this.add = add;
// }
}
let myGenericNumber = new GenericNumber<number>();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = function (x: number, y: number) {
return x + y;
};
let stringNumeric = new GenericNumber<string>();
stringNumeric.zeroValue = '';
stringNumeric.add = function (x: string, y: string) {
return x + y;
};泛型约束
使用extends关键字来表示我们的约束
ts
interface Lengthwise {
length: number;
}
function loggingIdentity<Type extends Lengthwise>(arg: Type): Type {
console.log(arg.length);
return arg;
}
loggingIdentity({ length: 10, value: 3 }); // OK在泛型约束中使用类型参数
ts
function getProperty<Type, Key extends keyof Type>(arg: Type, key: Key) {
return arg[key];
}
let x = { a: 1, b: 2, c: 3, d: 4 };
getProperty(x, 'a'); // OK
// getProperty(x, 'm'); // Error: Argument of type '"m"' is not在泛型中使用类类型
通过构造函数引用类类型
ts
function create<Type>(c: { new (): Type }): Type {
return new c();
}更高级的示例: 使用原型属性来推断和约束构造函数和类类型的实例端之间的关系。
ts
class BeeKeeper {
hasMask: boolean = true;
}
class ZooKeeper {
nameTag: string = 'Mikle';
}
class Animal {
numLegs: number = 4;
}
class Bee extends Animal {
numLegs: number = 6;
keeper: BeeKeeper = new BeeKeeper();
}
class Lion extends Animal {
keeper: ZooKeeper = new ZooKeeper();
}
function createInstance<A extends Animal>(c: new () => A): A {
return new c();
}
createInstance(Lion).keeper.nameTag;
createInstance(Bee).keeper.hasMask;泛型参数默认值
ts
declare function create(): Container<HTMLDivElement, HTMLDivElement[]>;
declare function create<T extends HTMLElement>(): Container<T, T[]>;
declare function create<
T extends HTMLElement,
U extends HTMLElement[]
>(): Container<T, U>;使用泛型默认参数来简化
ts
declare function create<
T extends HTMLElement = HTMLDivElement,
U extends HTMLElement[] = T[]
>(element?: T, children?: U): Container<T, U>;
const div = create();
const p = create(new HTMLParagraphElement());