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);
相关推荐
哥谭居民00019 小时前
将一个组件的propName属性与父组件中的variable变量进行双向绑定的vue3(组件传值)
javascript·vue.js·typescript·npm·node.js·css3
一條狗11 小时前
隨筆20241226 ExcdlJs 將數據寫入excel
react.js·typescript·electron
冰红茶-Tea19 小时前
typescript数据类型(二)
前端·typescript
Web阿成2 天前
3.学习webpack配置 尝试打包ts文件
前端·学习·webpack·typescript
j喬乔3 天前
Node导入不了命名函数?记一次Bug的探索
typescript·node.js
yg_小小程序员3 天前
vue3中使用vuedraggable实现拖拽
typescript·vue
高山我梦口香糖3 天前
[react 3种方法] 获取ant组件ref用ts如何定义?
typescript·react
prall4 天前
实战小技巧:下划线转驼峰篇
前端·typescript
一條狗5 天前
隨筆 20241224 ts寫入excel表
开发语言·前端·typescript
轻口味6 天前
配置TypeScript:tsconfig.json详解
ubuntu·typescript·json