我不明白为什么这个非常简短的TypeScript片段:
type R<B> = (b: B | undefined) => {};
type W = (z: Z) => Z;
type Z = <B>(r: R<B>) => B;
interface BB {someKey: number}
const result: Z = (_r: R<BB>) => ({ someKey: 123 });
导致此错误:
Type '(_r: R<BB>) => { someKey: number; }' is not assignable to type 'Z'.
Types of parameters '_r' and 'r' are incompatible.
Types of parameters 'b' and 'b' are incompatible.
Type 'BB' is not assignable to type 'B'.
任何人都可以帮助我理解TypeScript的类型推断是如何工作的吗? 以下是TypeScript playground
上代码段的链接答案 0 :(得分:0)
(为了便于理解其他人,我将使用Array<T>
代替R<B>
和number
代替BB
,我将重命名{ {1}} Z
GenericArrayPicker
并且W
无法输入,因此我将其删除。如果您想将其切换回来,则可以。错误完全相同,但希望下面的术语更直观。)
您的主要错误是试图说非泛型函数是通用的。请注意以下类型:
type GenericArrayPicker = <T>(arr: Array<T>) => T;
这是泛型函数类型,其中类型参数T
是函数的调用者所需的任何内容。让我们说我们实际上有这种类型的功能:
declare const genericArrayPicker: GenericArrayPicker;
来电者可以明确地选择T
:
genericArrayPicker<string>(["foo", "bar"]); // returns a string
或隐式允许编译器从调用站点推断出它:
genericArrayPicker(["foo", "bar"]); // T still inferred as string
现在,以下函数不泛型:
const numberArrayPicker =
(arr: Array<number>) => 17;
它仅适用于数字数组。如果检查其类型,则为(arr: Array<number>) => number
。您无法使用genericArrayPicker
:
numberArrayPicker(["foo", "bar"]); // error!
这应该是numberArrayPicker
与GenericArrayPicker
类型不匹配的提示。如果您尝试将其分配给GenericArrayPicker
,则会收到警告:
const result: GenericArrayPicker = numberArrayPicker; // error!
// T is not assignable to number
声明&#34; T
不能转让给number
&#34;可能看起来很奇怪。更明确的陈述是numberArrayPicker
仅适用于函数(T
)的实现者选择的类型参数number
的值。但是,调用者,而不是实施者,可以选择T
的值。这是universal and existential type quantification之间的差异; TypeScript仅支持通用类型量化(调用者选择类型,实现者必须接受调用者选择的任何内容),而不是存在类型量化(实现者选择类型,调用者必须接受实现者选择的任何内容)。
希望这是有道理的。祝你好运。