TS --- 泛型

107 阅读2分钟

「这是我参与2022首次更文挑战的第17天,活动详情查看:2022首次更文挑战

泛型

基本使用

// 泛型变量的定义在函数名后边,参数类别的前边
const getArr = <T>(value: T, num = 5): T[] => {
  return new Array(num).fill(value)
}

// 在实际调用的时候,我们可以显示的传入泛型变量所代表的值
getArr<number>(5)

// 如果我们不显示确定对应泛型变量的值
// 那么TypeScript的类型检测系统会自动根据我们所传入的value属性的值来确定对应泛型变量的类型
getArr('Klaus') // 此时泛型变量T的类型是 string
// 我们也可以同时使用多个泛型变量
function getTuple<T, U>(val1: T, val2: U) {
  return [val1, val2]
}

在函数中使用泛型

type Sum = <T>(value: T, num?: number) => T[]

// 虽然在实际定义函数的时候, value的类型是any
// 但是在函数的类型中,value的类型是泛型T
// 所以实际value所对应的类型会取决于实际传入的实参的类型,而不会是any
const sum: Sum = (value: any, num = 5) => {
  return new Array(num).fill(value)
}

sum('abc') //  type value = string
sum(2) // type value = number

在别名中使用

type Sum = <T>(value: T, num?: number) => T[]

在接口中使用

// 此时泛型变量T 只能在函数这个粒度上进行使用
interface sum {
  <T>(value: T, num?: number): T[]
}
// 我们也可以将泛型变量提升到整个接口范围内
// 这样所有在接口内部定义的内容都可以使用该泛型变量
interface sum<T> {
  <T>(value: T, num?: number): T[]
	count: T
}

泛型约束

默认情况下,泛型变量的类型是不被限制的,也就是说默认情况下泛型变量的类型都是any类型

但是很多时候,我们需要给泛型变量添加上对应的类型约束,以限制可以传入的泛型变量的类型

此时就可以使用泛型约束

// 使用extends关键字来对泛型变量进行约束
// T extends { length: number } 表示的是 传入的泛型变量的类型必须是具有length属性的值
function getLength<T extends { length: number }> {
  return T.length
}
function getValue<T, K extends keyof T>(obj: T, key: K) {
  return obj[key]
}

const obj = {
  a: 'aa',
  b: 'bb'
}

// keyof v 获取的是索引类型 对应的是v中所有key的联合 在这里就是 'a' | 'b'
// valueof v 获取的也是索引类型 对应的是v中所有值的联合 在这里就是 'aa' | 'bb'
getValue(obj, 'a')