为什么要用泛型

  • 许多时候,标注的具体类型并不能确定,比如一个函数的参数类型
  • 这个时候这种定义过程不确定类型的需求就可以通过泛型来解决
  • 泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性
  • 泛型T作用域只限于函数内部使用

    泛型函数

  • 首先,我们来实现一个函数 createArray,它可以创建一个指定长度的数组,同时将每一项都填充一个默认值

  1. function createArray(length: number, value: any): Array<any> {
  2. let result: any = []
  3. for (let i = 0; i < length; i++) {
  4. result[i] = value
  5. }
  6. return result
  7. }
  8. let result = createArray(3, 'x')

如果像这样将传入参数设置为any类型,不能得到准确的返回类型
如果使用泛型,我们就能约束我们想要的结果

  1. function createArray2<T>(length: number, value: T): Array<T> {
  2. let result: T[] = []
  3. for (let i = 0; i < length; i++) {
  4. result[i] = value
  5. }
  6. return result
  7. }
  8. let result2 = createArray2<string>(3, 'x')

泛型类

  1. class MyArray<T> {
  2. private list: T[] = []
  3. add(value: T) {
  4. this.list.push(value)
  5. }
  6. getMax(): T {
  7. let result = this.list[0]
  8. for (let i = 0; i < this.list.length; i++) {
  9. if (this.list[i] > result) {
  10. result = this.list[i]
  11. }
  12. }
  13. return result
  14. }
  15. }
  16. let arr = new MyArray<number>()
  17. arr.add(1)
  18. arr.add(2)
  19. arr.add(3)
  20. let ret = arr.getMax()
  21. console.log(ret)

泛型与new

  1. function factory<T>(type: { new (): T }): T {
  2. return new type()
  3. }
  4. const arr = factory<string[]>(Array)

泛型接口

  • 泛型接口可以用来约束函数

后端提供了一些接口,用以返回一些数据,依据返回的数据格式定义如下接口:

  1. interface IResponseData {
  2. code: number;
  3. message?: string;
  4. data: any; // 现在无法确定接口数据类型
  5. }
  • 但是,我们会发现该接口的 data 项的具体类型不确定,不同的接口会返回的数据是不一样的
  • 当我们想根据具体当前请求的接口返回具体 data 格式的时候,就比较麻烦了,因为 getData 并不清楚你调用的具体接口是什么,对应的数据又会是什么样的
  • 这个时候我们可以对 接口数据IResponseData 使用泛型 ```typescript interface IResponseData { code: number message?: string data: T }

// 用户接口 interface IResponseUserData { id: number username: string email: string } // 文章接口 interface IResponseArticleData { id: number title: string author: IResponseUserData }

async function getData(url: string) { let response = await fetch(url) let data: Promise> = await response.json() return data }

;(async function () { let userData = await getData(‘/user’) userData.data.id

let articleData = await getData(‘/article’) articleData.data.author })()

  1. <a name="KSA0g"></a>
  2. ## 多个泛型
  3. ```typescript
  4. function swap<A, B>(tuple: [A, B]): [B, A] {
  5. return [tuple[1], tuple[0]]
  6. }
  7. let swapped = swap<string, number>(['a', 1])
  8. console.log(swapped)
  9. console.log(swapped[0].toFixed(2))
  10. console.log(swapped[1].length)

泛型约束

  • 在函数中使用泛型的时候,由于预先并不知道泛型的类型,所以不能随意访问相应类型的属性或方法。 ```typescript function logger(val: T) { console.log(val.length) //直接访问会报错 } //可以让泛型继承一个接口 interface LengthWise { length: number } //可以让泛型继承一个接口 function logger2(val: T) { console.log(val.length) } logger2(‘acg’) logger2(1)

```