1. 泛型是什么

泛型,顾名思义,就是能够实用于多个类型,应用类型变量比方T帮忙咱们捕捉传入的类型,之后咱们就能够持续应用这个类型。

如下定义了一个identity泛型函数,<T>增加了类型变量T,它就能够帮忙捕捉咱们传入的变量value的类型,而后再次应用T作为返回值类型,这样就束缚了参数类型和返回值类型是雷同的了。

function identity <T>(value: T) : T {  return value;}

2. 泛型类型和泛型接口

const myIdentity: <T>(arg: T) => T = identity;

泛型类型和非泛型类型没有什么区别,只是传入了类型参数。

咱们还能够应用对象字面量的模式来申明函数类型:

const myIdentity: { <T>(arg: T): T } = identity;

这样就引入了泛型接口:

interface GenericIdentityFn {    <T>(arg: T): T;}const myIdentity: GenericIdentityFn = identity;

再进一步把类型变量T作为接口的参数,应用接口的时候再传入类型参数,就锁定了函数中应用的类型:

interface GenericIdentityFn<T> {    (arg: T): T;}const myIdentity: GenericIdentityFn<number> = identity;

3. 泛型类

在类名前面跟上类型变量,就能够在类中应用这些泛型类型。

class GenericPerson<T, U> {    name: T;  getAge: (age: U) => U;}let person = new GenericPerson<string, number>();person.name = 'Jane';person.getAge = function (x) { return x; };person.getAge(2);

4. 何时应用泛型

当接口、函数或类要解决多种数据类型并且在其中多个中央应用该类型的时候。

5. 泛型束缚

通常用接口来形容约束条件,用extends实现束缚。

// 传入合乎束缚类型的值,必须蕴含length属性interface Lengthwise {    length: number;}function loggingIdentity<T extends Lengthwise>(arg: T): T {    console.log(arg.length);     return arg;}
// 通过 K extends keyof T 确保参数 key 肯定是对象中含有的键,这样就不会产生运行时谬误function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {  return obj[key];}

6. 泛型条件类型

条件类型会以一个条件表达式进行类型关系检测,从而在两种类型中抉择其一:

T extends U ? X : Y

通常会联合推断关键字infer来应用:

type ParamType<T> = T extends (...args: infer P) => any ? P : T;

这样就能够实现类型抽取,如果T能够赋值给(...args: infer P) => any,那么返回参数P,否则返回T自身的类型。