泛型
通过传递的值(类型)来决定具体的类型。相当于动态类型
。
用法就是在名字的后面加上<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。