多态匿名函数类型别名

hom*_*mam 3 javascript flowtype

似乎命名function()语法与非同义函数语法的类型去除之间存在细微差别:

type F<X, Y> = (x: X) => Y

// works:
function apply<X, Y>(f: F<X, Y>, x: X) : Y {
    return f(x)
}

// works:
const apply0 : <X, Y>(f: F, x: X) => Y = (f, x) => f(x)

// doesn't work
const apply1 : <X, Y>(f: F<X, Y>, x: X) => Y = (f, x) => f(x)
Run Code Online (Sandbox Code Playgroud)

流控制台代码段

我需要从任何引用中删除泛型类型注释,以F<X, Y>apply类型检查器的匿名函数的参数中键入.

这是违反直觉的.

[编辑:]但似乎Flow能够键入检查apply1调用,即使它无法键入检查apply1本身:

apply1(x => x * 2, 'a') // error: ^ string. This type is incompatible with
apply1(x => x * 2, 1) // works
Run Code Online (Sandbox Code Playgroud)

更普遍:

// works:
type Apply<X, Y> = <X, Y>(f: F, x: X) => Y

const apply : Apply = (f, x) => f(x)    


// doesn't work:
type Apply1<X, Y> = <X, Y>(f: F<X, Y>, x: X) => Y

const apply1 : Apply1 = (f, x) => f(x)
Run Code Online (Sandbox Code Playgroud)

流控制台代码段

我必须X, Y从类型别名的参数中删除泛型类型注释,Apply以便对其进行类型检查.

这是预期的行为还是我错过了什么?

Gab*_*evi 5

TL; DR:试试

const apply1 = <X, Y>(f: F<X, Y>, x: X): Y => f(x)
Run Code Online (Sandbox Code Playgroud)

说明

首先,正如注释中提到的@squint,F没有类型参数隐式意味着F<any, any>,这就是为什么apply0在你的例子中起作用.

那你为什么apply1会有错误呢?嗯,这是因为Flow不会推断出泛型.所以当你写的时候

const apply1 : <X, Y>(f: F<X, Y>, x: X) => Y = (f, x) => f(x)
Run Code Online (Sandbox Code Playgroud)

任务的右侧是

(f, x) => f(x)
Run Code Online (Sandbox Code Playgroud)

和Flow不能推断出这个箭头函数是多态的.所以你可以像这样在RHS中添加类型参数:

const apply1 : <X, Y>(f: F<X, Y>, x: X) => Y = <X, Y>(f: F<X, Y>, x: X): Y => f(x)
Run Code Online (Sandbox Code Playgroud)

这应该可以解决错误.但此时,左侧的类型注释不再是必需的.所以你可以简化它

const apply1 = <X, Y>(f: F<X, Y>, x: X): Y => f(x)
Run Code Online (Sandbox Code Playgroud)

进一步阅读

Avik Chaudhuri写了一个关于类似堆栈溢出问题的简短解释,后者又链接到GitHub上类似答案