乐趣区

关于typescript:关于TS的泛型

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 自身的类型。

退出移动版