TS中的泛型

156 阅读1分钟

泛型

书写某个函数时,会丢失一些类型信息(多个位置的类型应该保持一致或有关联的信息)

  • 泛型:指附属于函数,类,接口别名之上的类型
  • 在函数中使用泛型,在函数名之后写上<泛型名称>
  • 泛型相当于一个类型变量,在定义时,无法预知具体类型,可以用该变量来代替;只有到调用时,才能确定它的类型
  • 很多时候,ts会智能的根据传递的参数,推导出泛型的具体类型;如果无法完成推导,并且又没有传递具体类型,默认为空对象
// 函数使用泛型
function take<T>(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
}

take<number>([1,2,3], 2 )

// 类型别名 
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 = [1,2,3,4,5]
console.log(filter(arr, n => n % 2 !== 0 ))

泛型约束

  • 用于限制泛型的取值
// 将某个对象的name属性的每个单词的首字母大小,然后将该对象返回
interface hasNameProperty {
  name: string
}

// 使用extends使得T具有接口hasNameProperty的属性,不约束的话,obj.name会报错,因为函数接收的参数不知道识哪一种类型
function nameToUpperCase<T extends hasNameProperty>(obj: T): T{
  obj.name = obj.name.split(" ")
    .map(str => str[0].toUpperCase + str.substr(1))
    .join(" ")
  return obj
}

const user = {
  name: "zero",
  age: 18
}

const newUser = nameToUpperCase(user)

多泛型

  • 依赖多种类型
// 将两个数组进行混合[1,2,3] ['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 result: (T | K)[] = []
  for (let i = 0; i < arr1.length, i++){
    result.push(arr1[i])
    result.push(arr2[i])
  }
  return result;
}

mixinArray([1,2,3], ['a','b','c'])