Skip to content

泛型

通过传递的值(类型)来决定具体的类型。相当于动态类型

用法就是在名字的后面加上<T>

T呢就是类型的一个变量名,用T这个字母是因为Type类型这个单词。

数组泛型

我们定义一个数组的类型的时候有两种方法:

ts
const array: number[] = [1, 2, 3]
ts
const array: array<number> = [4, 5, 6]

其中:

1就是普通的方法,number[]代表这个是一个由number类型组成的数组[]

2就是泛型的方法,通过<>传入number类型,代表这是一个number类型的数组

函数泛型

ts
function sub<T, K>(a: T, b: K): Array<T | K> {
  return [a, b]
}

sub('123', false) // sub<string, Boolean>

上面的例子中,使用了两个泛型参数:T & K,这样就实现了对两个形参的类型定义,同时返回值也是由泛型的类型决定的。这就是通过泛型实现了动态类型

泛型约束

泛型过于灵活,如何加上一些限制呢

例子:

需求:我们需要一个getLen(param)函数,return传参的length属性。

问题:不是所有数据类型都有length这个属性。

ts
function getLen<T>(param: T) {
  return param.length // 此时报错:类型T上不存在属性length
}

这个时候就需要泛型约束:

ts
interface Len {
  length: number
}
function getLen<T extends Len>(param: T) {
  return param.length // √
}

上面的例子中,我们通过接口Len对泛型进行了约束,约束T类型为具有length属性的类型。

约束函数的参数

需求:有一个getValue(obj, key)函数,第一个参数为一个object,第二个参数为需要获取值的key,返回值为obj的key对应的值

问题:怎么保证第二个参数key,传入的实参一定是第一个参数obj存在的key呢?

解决:

ts
function getValue<T extends object, K extends keyof T>(obj: T, key: K) {
  return obj[key]
}

const obj = {
  name: 'zhang san',
  age: 18
}

getValue(obj, 'gender') // 类型obj上不存在属性gender
getValue(obj, 'name') // √

上面的代码中,使用T extends object约束了T是一个object类型,K通过keyof T约束了其为类型T中存在的key。