Typescript-infer关键字

avatar

Typescript-infer关键字

infer

infer 属于Typescript中的关键字,作用是安全的在泛型类型中获取参数类型

举个例子:

1
2
3
type getType<T> = T extends { a: infer U } ? U : never

type paramsType = getType<{ a: string }> // useParamsType = string

这是最基本的infer使用方式,目的为了提取泛型类型中参数的类型。而这里要引入一种概念:协变逆变

协变

例子:

1
2
3
4
// 协变
type getParamsType<T> = T extends { a: infer U, b: infer U } ? U : never
// useParamsType = string | number
type useParamsType = getParamsType<{ a: string, b: number }>

这里通过 infer U 关键字同时获取泛型T的参数 ab ,此时泛型U时而为string,时而为number,所以是或关系,这就是协变

逆变

例子:

1
2
3
type getIntersection<T> = T extends (a: infer U, b: infer U) => void ? U : never
// Intersection = string & number
type Intersection = getIntersection<(a: string, b: number)=> void>

这里通过 infer U 关键字同时获取泛型T的参数 ab ,此时泛型U时而为string,时而为number,这里为什么不是或关系,而是且关系呢?其实协变或逆变与 infer 参数位置有关,在 TypeScript 中,对象、类、数组和函数的返回值类型都是协变关系,而函数的参数类型是逆变关系,所以 infer 位置如果在函数参数上,就会遵循逆变原则

逆变与协变:

  • 协变(co-variant):类型收敛。
  • 逆变(contra-variant):类型发散

总结

infer 关键字让我们拥有深入展开泛型的结构,并 Pick 出其中任何位置的类型,并作为临时变量用于最终返回类型的能力

参考 帖子:精读《Typescript infer 关键字》