条件类型中的 TypeScript 类型推断
Posted
技术标签:
【中文标题】条件类型中的 TypeScript 类型推断【英文标题】:TypeScript type inference in conditional types 【发布时间】:2018-10-20 03:27:55 【问题描述】:我对以下示例中的类型推断方式感到困惑
type RetType<T> = T extends (...args: (infer I)[]) => infer R ? [I, R] : any;
type X = (a: number, b: string) => void;
type Q = RetType<X>;
如果您将鼠标悬停在操场上的 Q
类型上,您将获得 [number & string, void]
。这很令人困惑,因为我希望I
被推断为number | string
(联合)而不是number & string
(交集)。
有人理解为什么输入参数被推断为交集而不是联合吗?
【问题讨论】:
【参考方案1】:这可能不是您要寻找的答案或解释,但在docs 中提到了这一点:
同样,同一类型变量在逆变位置的多个候选会导致推断出交集类型:
type Bar<T> = T extends a: (x: infer U) => void, b: (x: infer U) => void ? U : never; type T20 = Bar< a: (x: string) => void, b: (x: string) => void >; // string type T21 = Bar< a: (x: string) => void, b: (x: number) => void >; // string & number
【讨论】:
【参考方案2】:TL;DR: 因为无论I
是什么,它都必须可分配给所有函数类型T
的参数。
这是因为函数参数是反变体。这只是意味着要使用一个函数代替另一个函数,它的参数类型必须与另一个函数相同或更通用。看一个例子就很明显了:
type f: (arg: string) => string;
type g: (arg: "foo") => string;
// f is assignable to g, since a function expecting
// to receive any string should have no problem accepting
// the specific string "foo".
// However, the reverse isn't true. You can't assign g to f,
// since g expects to receive exactly the string "foo" for its
// argument, but if it's used in place of f, it can receive any string.
换句话说,f
可以分配给g
,因为g
的参数可以分配给f
。这种逆转是相反部分。
因此,如果T
是某个神秘函数类型(...args: I[]) => R
的子类型,则自变量逆变告诉我们I
必须可分配给T
的自变量类型。
因此,T extends (...args: (infer I)[]) => infer R
告诉 typescript 推断出某个单一类型 I
以便可以使用 I
代替 T
的 any 参数。
因此,对于您的类型X
,无论I
是什么,它都必须可以分配给两个参数。由于参数类型分别是number
和string
,我们问:什么类型可以分配给这两个?
好吧,number & string
。
*更多信息,您可能有兴趣阅读co and contra-variance。
【讨论】:
这是有道理的。一输入问题,我就记得函数参数是逆变的。以上是关于条件类型中的 TypeScript 类型推断的主要内容,如果未能解决你的问题,请参考以下文章