typescript 泛型

152 阅读2分钟

泛型的使用场景

先来说说什么时候使用泛型,先举个🌰

下面定义了一个函数,入参array可以是数字数组和字符串数组

function getArrayValue(array, n) {
  let value;
  for (let i = 0; i < array.length; i++) {
    if (array[i] === n) {
      value =  array[i]
      break;
    }
  }
  return value;
}

console.log(getArrayValue(['a', 'b', 'c'], 'a'))
console.log(getArrayValue([1, 2, 3], 3))

接下来我们给入参和函数返回值定义类型

function getArrayValue(array: string | any[], n: string | number): string | number {
  let value;
  for (let i = 0; i < array.length; i++) {
    if (array[i] === n) {
      value =  array[i]
      break;
    }
  }
  return value;
}

console.log(getArrayValue(['a', 'b', 'c'], 'a'))
console.log(getArrayValue([1, 2, 3], 3))

这样看可读性比较差,万一入参的类型很多的话那会有很长一串

这时候可能会有人说直接用any,但是用any的话会有个问题,该函数返回值的类型其实是比较明确的,根据传入的array来的,用any不准确,无法类型约束,有错误不易暴露

那泛型的使用场景就来了:定义时类型不确定,使用时知道类型,以上代码就可以改成下面这样:

function getArrayValue<T>(array: T[], n: T): T | undefined {
  let value
  for (let i = 0; i < array.length; i++) {
    if (array[i] === n) {
      value = array[i]
      break
    }
  }
  return value
}

console.log(getArrayValue(['a', 'b', 'c'], 'a'))
console.log(getArrayValue([1, 2, 3], 3))

这样使用时如果传入字符串数组,则第二个参数和返回值都会被要求是数组,传入数字数组,则第二个参数和返回值都会被要求是数字,可读性好,约束性好

通过以上场景,我们来理解下泛型的基本概念和作用

泛型的基本概念和作用

泛型允许在定义函数、接口、类或类型别名时使用类型参数,这些类型参数在实际使用时会被具体的类型所替换。通过这种方式,可以编写出更加通用和灵活的代码,避免重复编写多份几乎相同的代码,同时保持类型安全‌

使用方式

函数、接口、类或类型别名的名称后面加上<泛型名称>

举几个🌰

function f1<T>(arg: T): T {  
    return arg;  
}
function f2<T, U>(arg: T, urg: U): T | U {  
  if (条件1) {
      return arg;  
  } else {
      return urg;  
  }
}

上篇文章的pick

type MyPick<T, key extends keyof T> = {
  [AttrKey in key]: T[AttrKey]
}