TS之泛型

一、泛型

泛型: 是指附属于类型、类、接口、类型别名之上的类型。

  • 书写某个函数时,会丢失一些类型信息(多个位置的类型应该保持一致或有关联的信息)。
  • 泛型相当于是一个类型变量,在定义时,无法预先知道具体的类型,可以用该变量来代替,只有到调用时,才能确定它的类型。
  • 很多时候, TS 会智能的根据传递的参数,推导出泛型的具体类型。
  • 如果无法完成推导,并且又没有传递具体的类型,默认为空对象
  • 泛型可以设置默认值。

1.在函数中使用泛型

在函数名之后写上 <泛型名称> :

为函数指定一个泛型,名称为 T ,调用函数时传递一个 number 类型,则 T 为 number 类型,可以作为函数参数、函数返回值、和函数里面数值类型使用。下方示例中,为 T 指定了默认类型为 number 。

ts 复制代码
function take<T = number>(arr:T[],n:number): T[] { 
  if (n >= arr.length) { 
    return arr;
  }
  const newArr: T[] = []
  for (let i = 0; i < n; i++) { 
    newArr.push(arr[i])
  }
  return newArr
}
const newArr = take<number>([1, 2, 3, 4, 5], 2)
console.log(newArr); // [ 1, 2 ]

2.在类型别名、接口和类中使用泛型

类型别名直接在名称后写上 <泛型名称> :

ts 复制代码
type callback<T> = (n: T, i: number) => boolean
function filter<T>(arr: T[], callback: callback<T>): T[] {
  const newArr: T[] = []
  arr.forEach((n, i) => { 
    if (callback(n, i)) { 
      newArr.push(n)
    }
  })
  return newArr
}
const arr = [3, 4, 5]
console.log(filter<number>(arr, n => n % 2 !== 0)); // [ 3, 5 ]

接口直接在名称后写上 <泛型名称> :

ts 复制代码
interface callback<T> {
  (n: T, i: number): boolean
}
function filter<T>(arr: T[], callback: callback<T>): T[] {
  const newArr: T[] = []
  arr.forEach((n, i) => { 
    if (callback(n, i)) { 
      newArr.push(n)
    }
  })
  return newArr
}
const arr = [3, 4, 5]
console.log(filter<number>(arr, n=> n % 2 !== 0)); // [ 3, 5 ]

直接在名称后写上 <泛型名称> :

ArrayHelper.ts :

ts 复制代码
export class ArrayHelper<T> { 
  constructor(private arr: T[]) { }
 
  take(n:number): T[] { 
    if (n >= this.arr.length) { 
      return this.arr;
    }
    const newArr: T[] = []
    for (let i = 0; i < n; i++) { 
      newArr.push(this.arr[i])
    }
    return newArr
  }
 
  shuffle() { 
    for (let i = 0; i < this.arr.length; i++) {
      const targetIndex = this.getRandom(0, this.arr.length)
      const temp = this.arr[i]
      this.arr[i] = this.arr[targetIndex]
      this.arr[targetIndex] = temp
    }
  }
 
  private getRandom(min: number, max: number) { 
    const dec = max - min
    return Math.floor(Math.random() * dec + max)
  }
}

index.ts :

由于 TS 自带的类型推导,所以 <泛型名称> 有时可以省略。

二、泛型约束

泛型约束: 用于限制泛型的取值。

在下方代码中定义一个接口,里面有一个属性 name 为字符串 类型,函数中使用继承了该接口属性的泛型作为函数的参数和返回值。 泛型约束满足鸭子辨型法。

ts 复制代码
interface hasNameProperty {
  name: string
}
const person = {
  name: "rata li",
  age: 18,
  gender:"男"
}
/**
 * 将某个对象的name属性的每个单词的首字母转换为大写,然后返回该对象
 */
function nameToUpperCase<T extends hasNameProperty>(obj:T): T {
  obj.name = obj.name
    .split(" ")
    .map(i => i[0].toUpperCase() + i.substring(1))
    .join(" ")
  return obj
}
const newPerson = nameToUpperCase(person)
console.log(newO.name) // Rata Li

此时,参数中必须包含 name 属性,如果去掉对象 person 中的 name 属性,则会报错:

三、多泛型

多泛型:写一些函数或者类时,依赖多个类型的时候需要使用多泛型。

ts 复制代码
/**
 * 将两个数组进行混合,[1,3,4] ["a","b","c"] => [1,"a",2,"b",3,"c"]
 */
function mixinArray<T, K>(arr1: T[], arr2: K[]): (T | K)[] {
  if (arr1.length !== arr2.length) { 
    throw new Error("两个数组长度不等")
  }
  let newArr: (T | K)[] = []
  for (let i = 0; i < arr1.length; i++) { 
    newArr.push(arr1[i]);
    newArr.push(arr2[i]);
  }
  return newArr
}
const arr = mixinArray([1, 2, 3], ["a", "b", "c"])
console.log(arr);
相关推荐
清灵xmf5 小时前
TypeScript 类型进阶指南
javascript·typescript·泛型·t·infer
Amd79412 小时前
Nuxt.js 应用中的 prepare:types 事件钩子详解
typescript·自定义·配置·nuxt·构建·钩子·类型
王解1 天前
Jest项目实战(2): 项目开发与测试
前端·javascript·react.js·arcgis·typescript·单元测试
鸿蒙开天组●2 天前
鸿蒙进阶篇-网格布局 Grid/GridItem(二)
前端·华为·typescript·harmonyos·grid·mate70
zhizhiqiuya2 天前
第二章 TypeScript 函数详解
前端·javascript·typescript
初遇你时动了情2 天前
react 18 react-router-dom V6 路由传参的几种方式
react.js·typescript·react-router
王解2 天前
Jest进阶知识:深入测试 React Hooks-确保自定义逻辑的可靠性
前端·javascript·react.js·typescript·单元测试·前端框架
_jiang2 天前
nestjs 入门实战最强篇
redis·typescript·nestjs
清清ww3 天前
【TS】九天学会TS语法---计划篇
前端·typescript
努力变厉害的小超超3 天前
TypeScript中的类型注解、Interface接口、泛型
javascript·typescript