条件类型中的TypeScript类型推断

Dav*_*yan 4 types type-inference typescript

在以下示例中,我对如何推断类型感到困惑

type RetType<T> = T extends (...args: (infer I)[]) => infer R ? [I, R] : any;
type X = (a: number, b: string) => void;
type Q = RetType<X>;
Run Code Online (Sandbox Code Playgroud)

如果将鼠标悬停Q在操场上的类型上,您将得到[number & string, void]。之所以令人困惑,是因为我希望I将其推断为number | string(联合)而不是number & string(交集)。

有谁知道为什么将输入参数推断为交集而不是并集?

CRi*_*ice 5

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.
Run Code Online (Sandbox Code Playgroud)

换句话说,f之所以可分配给,是g因为g的自变量可分配给f的。逆转是相反的部分。

因此,如果T是某个神秘函数类型的子类型(...args: I[]) => R,则参数相反方差告诉我们I必须将其分配给的参数类型T

因此,T extends (...args: (infer I)[]) => infer R告诉typescript推断某种单一类型I,以便I可以代替的任何参数使用T

因此,对于您的type X,无论I是什么,它都必须可分配给两个参数,这是事实。由于参数类型分别为numberstring,我们问:这两个参数都可以分配什么类型?

好吧,number & string


*有关更多信息,您可能对阅读协方差和逆方差感兴趣。