重拾Typescript之泛型

752 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第2天,点击查看活动详情

雄关漫漫真如铁,而今迈步从头越,ts的学习还是被我拆成知识点的形式去学习吧,这样针对每个知识点在自己复习的时候更清晰吧。

1.函数泛型:

先来看下下面的场景:

function joinExample(first: string | number, second: string | number){
  return `${first}${second}`;
}

那么如果我想让参数firstnumber类型的时候,second也为number类型,改如何处理呢?

泛型,顾名思义就是泛指的类型,来看下面使用泛型解决上述问题的例子:

function join<T, P>(first: T, second: P) {
  return `${first}${second}`;
}

function anotherJoin<T>(first: T, second: T): T {
  return first;
}

// join<number, string>(1, '1');
// map<string>(['123']);
join(1, '1');

定义某个类型数组的方法:

下面例子中的两种数组的定义是一样的。

// T[](某个类型数组的写法)
function map<T>(params: Array<T>) {
  return params;
}

// 或者
function map1<T>(params:T[]){
  return params;
}

2.类中的泛型以及泛型的类型:

1.类中的泛型:

  • DataManager是一个类,data是一个string的数组
  • getItem传入一个number类型的索引,返回data中相应的项
class DataManager{
  constructor(private data:string[]){

  }
  getItem(index:number):string{
    return this.data[index];
  }
}

const data = new DataManager(["科比","艾弗森","麦迪","卡特"]);
data.getItem(0);

后续产品经理说,这个data不仅仅是string类型的数组,还要求可以是其他类型的数组:

class DataManager1{
  constructor(private data:string[] | number[]){

  }
  getItem(index:number):string | number{
    return this.data[index];
  }
}

如果这个data数组将来内部可能会是更多类型,那么联合类型的解决方案也就不是很方便了,因此有了泛型

class DataManager2<T>{
  constructor(private data: T[]){

  }
  getItem(index:number):T{
    return this.data[index];
  }
}
const data2 = new DataManager2<string>(["123","456"]);
data.getItem(1);

2.泛型继承interface接口的使用

如何能够让泛型拥有指定的属性(例如.name)?

  • 外部定义一个interface接口
  • 让泛型T通过extends去继承这个接口,在T继承了Item之后,T必须要有接口Item中定义的内容
interface Item {
  name:string;
}
//T继承了Item之后,T必须要有接口Item中所有的东西
class DataManager3<T extends Item>{
  constructor(private data: T[]){

  }
  getItem(index:number):string{
    return this.data[index].name;
  }
}
const data3 = new DataManager3([{name:"成为更好的自己"}]);

现在希望这个T只能是number或者是string类型,那么又该如何处理呢?

  • 直接让泛型继承类型
class DataManager4<T extends number | string>{
  constructor(private data:T[]){

  }
  getItem(index:number):T {
    return this.data[index];
  }
}

3.使用泛型作为一个具体的类型注解:

下面是一个拆解的形式,定义了一个函数gameBoy

const func: <T>(params:T) => T = gameBoy;

function gameBoy<T>(params:T){
  return params
}