在软件工程中,除了要创建一个一致的定义良好的API,还要考虑可重用性。
泛型即解决重用性的,一个组件可以支持多种类型的数据。

  1. // 泛型T
  2. function identity <T>(value: T): T {
  3. return value;
  4. }
  5. <= identity<number>(1);
  6. => 1

image.png
其中T是Type的意义,还有常见泛型变量代表的意思
K:表示对象中key键类型
V:表示对象中value类型
E:element表示元素类型

还能多个泛型
image.png
以上是显式地声明泛型,还可以让编译器自动辨识类型,隐式声明泛型

  1. function identity <T, U>(value: T, message: U): T {
  2. console.log(message)
  3. return value;
  4. }
  5. console.log(identity(68, "Semlinker"))

泛型接口

  1. interface Fn<T> {
  2. (arg: T): T
  3. }

泛型类

  1. class GenericNumber<T> {
  2. zeroValue: T;
  3. add: (x: T, y: T) => T
  4. }
  5. let myGenericNumber = new GenericNumber<number>();
  6. myGenericNumber.zeroValue = 0;
  7. myGenericNumber.add = function (x, y) {
  8. return x + y;
  9. }

泛型工具类型

typeof

获取一个变量声明或对象的类型

  1. interface Person {
  2. name: string;
  3. age: number;
  4. }
  5. const sem: Person = {name: 'sem', age: 13}
  6. type Sem = typeof sem; // => Person
  7. function toArray(x: number): Array<nubmer> {
  8. return [x]
  9. }
  10. type Func = typeof toArray; // (x: number) => Array<nubmer>

keyof

获取某种类型的所以键,其返回的类型是联合类型

  1. interface Person {
  2. name: string;
  3. age: number;
  4. }
  5. type K1 = keyof Person; // "name" | "age"
  6. type K2 = keyof Person[]; // "lenght" | "toString" | "pop" | "push" | "concat"...
  7. type K3 = keyof {[x: string]: Person}; // "string" | "number"

在typescript种支持两个索引签名,数字索引和字符串索引

  1. interface StringArray {
  2. // 字符串索引 : keyof StringArray => string | number
  3. [index: string]: string;
  4. }
  5. interface NumberArray {
  6. // 数字索引:keyof NumberArray => number
  7. [index: number]: string;
  8. }

字符串索引 : keyof StringArray => string | number的原因是:因为数字索引在JavaScript执行索引操作时会把数字索引转换为字符串索引,所以字符串所以支持两种类型:string | number

in

in用来便利枚举类型

  1. type Keys = "a" | "b" | "c"
  2. type Ojb = {
  3. [p in Keys]: any
  4. }
  5. => type Ojb = {
  6. a: any;
  7. b: any;
  8. c: any;
  9. }

infer

泛型条件

条件类型是指:我们可以根据某些条件得到不同的类型,这里所说的条件是类型兼容性约束。
使用**extends**关键字,也不一定要强制满足继承关系,而是检查是否满足结构兼容性。

  1. T extends U ? X : Y
  2. // 如果T可以赋值给U那么返回X类型,否则返回Y类型。

**
分布式条件类型在实例化过程中自动分布在联合类型上,例如 T extends U ? X : Y 的类型参数T是联合类型 A | B | C 被解析成 (A extends U ? X : Y) | (B extends U ? X : Y) | (C extends U ? X : Y).
https://mariusschulz.com/blog/conditional-types-in-typescript
https://github.com/Microsoft/TypeScript/pull/21316

类型约束

  1. function Foo<T>(params: T) {
  2. // Property 'length' does not exist on type 'T'
  3. // 此时泛型T中并不知道有length属性
  4. console.log(params.length);
  5. }

使用extends进行类型约束Ï

  1. type Length = {
  2. length: number;
  3. }
  4. function Foo<T extends Length>(params: T) {
  5. console.log(params.length);
  6. }

T extends Length用户告诉编译器,表示我们支持已经实现了Length接口的任何类型

泛型参数默认类型

  1. interface A<T=string> { name: T;
  2. }
  3. const strA: A = { name: "Semlinker" };
  4. const numB: A<number> = { name: 101 };