场景假设:我们有个黑盒类型Arr,明确知道Arr是一个数组,但确实不知道数组的元素是什么类型,这时候就可以有以下写法:
黑盒类型:
type Arr = Array<string | number>
获取方法:
type get<T> = T extends Array<infer U> ? U : T
获取的结果:
type B = get<Arr>
我们来具体分析一下上面的式子,重点是看这个获取方法
type Arr = Array<string | number>
1.我们这里的黑盒类型定义的非常明显,实际上在操作的时候,这个类型可以是一个非常复杂的类型
type get<T> = T extends Array<infer U> ? U : T
1.首先这个方法本身就是一个js三目运算符,
“?”前面的式子成立则返回U,不成立则返回T,T泛型就get方法参数
2.看一下“?”前面的式子 --- T extends Array<infer U> ?
T、U明显都表示泛型
extends一般在ts当中表示扩展,比如我们的类,比如interface的扩展,但在和泛型结合的时候表示“符合”
3.而infer则表示推断的占位(高中英语)
infer U 联合也就是表示“这个类型我不确定,就暂时表示为U吧”
那上面这个式子总的意思就是:这个T是否符合Array<U>的结构规则,符合的话,我这个U就能返回出来,
否则符合参数本身T
type B = get<Arr>
1.类似于将Arr类型传参入上面的get方法
整个就表示“Array<string|number> 是否符合Array<U>的结构规则”,
2.U的类型解构出来了并赋值给了type B
也就是infer U 也就是拿U 作为一个占位符,相当于“设了个X”,整个过程实际上就是在用三目运算写了个方程
下面给几个实例:
一、获取对象的value的类型
//获取所有的value的类型
type Obj1 = { name: string, age: number }
type get1<T> = T extends { name: infer U, age: infer C } ? [U, C] : T
type C = get1<Obj1>//[string,number]这样的一个元祖
//只获取单个value的类型
type Obj1 = { name: string, age: number }
type get2<T> = T extends { name: infer U } ? U : T
type D = get2<Obj1> //只是一个string类型
// 当然我们也可以有这样的写法
type get3<T> = T extends { name: infer U, age: infer U } ? U : T
type E = get3<Obj1> //string|number 的联合类型
二、获取函数的返回值:
// 尝试一下获取函数的返回值
type Fuc = (name: string, age: number) => (a: string, b: boolean) => void
type getFucReturn<T> = T extends (name: any, age: any) => infer U ? U : T
type F = getFucReturn<Fuc> //(a: string, b: boolean) => void
本人混饭吃大龄菜鸟一个,理解上可能有误,有错误之处请指出,多看多练,多看多练