[英]TypeScript type inference in conditional types
我對以下示例中的類型推斷方式感到困惑
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
(union)而不是number & string
(intersection)。
有沒有人理解為什么輸入參數被推斷為交集而不是聯合?
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
的任何參數。
所以對於你的類型X
,無論I
是什么,它都應該是真的,它必須可以分配給兩個參數。 由於參數類型分別是number
和string
,我們會問: 這兩種類型都可分配哪種類型?
好吧, number & string
。
*有關更多信息,您可能有興趣閱讀co和contra-variance 。
這可能不是您正在尋找的答案或解釋,但這在文檔中提到 :
同樣,反變量位置中相同類型變量的多個候選者會導致交叉類型被推斷:
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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.