需要帮助了解类型推断在此示例中的工作原理

时间:2018-05-21 18:27:56

标签: typescript

我不明白为什么这个非常简短的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

上代码段的链接

1 个答案:

答案 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!

这应该是numberArrayPickerGenericArrayPicker类型不匹配的提示。如果您尝试将其分配给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仅支持通用类型量化(调用者选择类型,实现者必须接受调用者选择的任何内容),而不是存在类型量化(实现者选择类型,调用者必须接受实现者选择的任何内容)。

希望这是有道理的。祝你好运。