初学TypeScript系列(六)

87 阅读3分钟

TypeScript 学习笔记.jpg 持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第3天,点击查看活动详情

接着之前的TypeScript系列文章,今天来学习TypeScript中的泛型。

泛型

指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定具体类型的一种特性。

<T> – T 被称为类型参数

泛型(Generics)允许同一个函数接受不同类型参数。相比于使用 any 类型,使用泛型来创建可复用的组件要更好,因为泛型会保留参数类型,保持代码的灵活性和可重用性。

简单举例说明:泛型函数

根据指定的数量 count(number类型) 和数据 value(不预先指定具体类型) ,创建一个指定长度的数组。

creatArray函数名后添加了 <T> (也可以是其他别的字母),其中 T 用来指代任意输入的类型,在函数内部就可以使用这个 T 类型(即在后面的输入 value: T 和输出 Array<T> 中使用)

const creatArray = <T>(value: T, count: number = 2) => {
  const arr: Array<T> = []
  for(let i = 0; i < count; i++){
    arr.push(value)
  }
  return arr
};
// 指定具体类型调用
const arr1 = creatArray<number>(11)
console.log(arr1) // [11, 11]
// ts做类型推论自动推算出来具体类型(根据传递的泛型参数)
const arr2 = creatArray('aa')
console.log(arr2) // ['aa','aa']

泛型变量

常见泛型变量:(只是一个约定好的规范,使用其它大写字母也可以)

  • T(Type):表示一个 TypeScript 类型
  • K(Key):表示对象中的键类型
  • V(Value):表示对象中的值类型
  • E(Element):表示元素类型

泛型接口

在定义接口时, 为接口中的属性或方法定义泛型类型。在使用接口时, 再指定具体的泛型类型

interface Person<T> {
  name: string;
  like: T;
}
// 本例中传入的“like”类型是字符串数组
const person1: Person<string[]> = {
  name: 'ConardLi',
  like: ['apple', 'banana', 'watermelon'],
}
//本例中传入的“like”类型是一个字符串
const person2: Person<string> = {
  name: 'Tom',
  like: 'pomegranate',
}

泛型类

与泛型接口类似,泛型也可以用于类的类型定义中

class  enumeration<T> {
  arr:T[] = [];
  add(value:T):T{
      this.arr.push(value);
      return value;
  }
  all():T[]{
      return this.arr;
  }
}
let number = new enumeration<number>();
number.add(1);
number.add(3);
number.add(5);
console.log(number.all()); // [1,3,5]

泛型约束

在函数内部使用泛型变量的时候,由于事先不知道它是哪种类型,所以不能随意的操作它的属性或方法。

默认情况下我们可以指定泛型为任意类型,但是有些情况下指定的类型需要满足某些条件,那么这个时候我们就可以使用泛型约束来实现

简单举例说明:获取一个参数的长度

对一个泛型参数取 length 属性, 会报错, 因为这个泛型 T 不一定包含属性 length

使用泛型约束,使用 extends 约束泛型<T>必须符合 LengthInterface 的形状,也就是必须包含 length 属性

interface LengthInterface{
  length:number
}
let getLength = <T extends LengthInterface>(value:T):T=>{
  console.log(value.length); // 4
  return value;
};
getLength('1234');
//getLength(7);  //报错:number没有length属性