// T 是一个抽象类型,只有在调用的时候才确定它的值
function reverse<T>(items: T[]): T[] {
var toreturn = [];
for (let i = items.length - 1; i >= 0; i--) {
toreturn.push(items[i]);
}
return toreturn;
}
泛型类型
// 泛型函数
function identity<T>(arg: T): T {
return arg;
}
// 普通接口
interface GenericIdentityFn {
// 泛型函数
<T>(arg: T): T;
}
// 泛型接口
interface GenericIdentityFn1<T> {
(arg: T): T;
}
let myIdentity = identity;
let myIdentity1: <T>(arg: T) => T = identity;
let myIdentity2: <U>(arg: U) => U = identity;
// {<T>(arg: T): T} 接口
let myIdentity3: { <T>(arg: T): T } = identity;
let myIdentity4: GenericIdentityFn = identity;
// 将泛型参数当作接口的参数
let myIdentity5: GenericIdentityFn1<number> = identity;
泛型类
// 泛型类
class GenericNumber<T> {
// 断言
// zeroValue!: T;
// add!: (x: T, y: T) => T;
zeroValue: T | undefined;
add: (x: T, y: T) => T = (x: any, y: any) => x + y;
}
let myGenericNumber = new GenericNumber<number>();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = function(x, y) { return x + y; };
class ZooKeeper {
nametag!: string;
}
class Animal {
numLegs!: number;
}
class Lion extends Animal {
keeper: ZooKeeper = new ZooKeeper();
}
function createInstance<A extends Animal>(C: new () => A): A {
return new C();
}
createInstance(Lion).keeper.nametag;
综合例子
// 创建一个泛型类
class Queue<T> {
private data: T[] = [];
push = (item: T) => this.data.push(item);
pop = (): T | undefined => this.data.shift();
}
// 简单的使用
// 泛型变量需要外部指定
const queue = new Queue<number>();
queue.push(0);
queue.push('1'); // Error:不能推入一个 `string`,只有 number 类型被允许
function reverse<T>(items: T[]): T[] {
const toreturn = [];
for (let i = items.length - 1; i >= 0; i--) {
toreturn.push(items[i]);
}
return toreturn;
}
const sample = [1, 2, 3];
// 这里泛型是指定了 number 类型
let reversed = reverse(sample);
reversed[0] = '1'; // Error
reversed = ['1', '2']; // Error
reversed[0] = 1; // ok
reversed = [1, 2]; // ok
function id<T>(arg: T): T {
return arg;
}
id<string>("lucifer"); // 完整的写法
id("lucifer"); // 基于类型推导的简写
// 泛型变量 T 默认参数 string
type A<T = string> = Array<T>;
const aa: A = [1]; // type 'number' is not assignable to type 'string'.
const bb: A = ["1"]; // ok
const cc: A<number> = [1]; // ok
泛型
设计泛型的关键目的是在成员之间提供有意义的约束,这些成员可以是
在更加一般化的场景,我们的类型可能并不固定已知,它和any有点像,只不过我们希望在any的基础上能够有更近一步的约束。其实就是在定义的时候不指定具体类型,用一个变量替代,使用时在指定类型替换泛型变量
常见:
Array<String>
例如:
泛型类型
泛型类
与接口一样,直接把泛型类型放在类后面,可以帮助我们确认类的所有属性都在使用相同的类型。
类有两部分:静态部分和实例部分。 泛型类指的是实例部分的类型,所以类的静态属性不能使用这个泛型类型。
泛型约束
现在这个泛型函数被定义了约束,因此它不再是适用于任意类型。我们需要传入符合约束类型的值,必须包含必须的属性(length),如果不约束,arg.length 会报错
在泛型里使用类类型
综合例子
泛型是对类型进行编程
区别于平时我们对值进行编程,泛型是对类型进行编程。
例如常见类型转换:
Partial
这里其实就是接收一个类型,经过处理后返回一个新的类型。
类型推导与默认参数
泛型也支持类型推导和默认参数
什么时候用泛型
Partial
进阶
泛型支持函数嵌套
泛型支持递归
// 官方 HTMLElement 的定义 declare var HTMLElement: { prototype: HTMLElement; new(): HTMLElement; }