多态匿名函数类型别名
Polymorphic Anonymous Functions Type Aliases
命名 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)
我需要从匿名 apply
函数的参数中对类型 F<X, Y>
的任何引用中删除泛型类型注释,类型检查器才能工作。
这是违反直觉的。
[编辑:]但似乎 Flow 能够键入检查 apply1
调用,即使它无法键入检查 apply1
本身:
apply1(x => x * 2, 'a') // error: ^ string. This type is incompatible with
apply1(x => x * 2, 1) // works
更一般地说:
// 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)
我必须从类型别名 Apply
的参数中删除泛型类型注释 X, Y
,以便 Flow 对其进行类型检查。
这是预期的行为还是我遗漏了什么?
TL;DR:尝试
const apply1 = <X, Y>(f: F<X, Y>, x: X): Y => f(x)
说明
首先,正如@squint 在评论中提到的,没有类型参数的 F
隐式意味着 F<any, any>
,这就是 apply0
在您的示例中有效的原因。
那为什么你的apply1
有错误呢?好吧,这是因为 Flow 不推断泛型。所以当你写
const apply1 : <X, Y>(f: F<X, Y>, x: X) => Y = (f, x) => f(x)
作业的右边是
(f, x) => f(x)
而且 Flow 不能推断出这个箭头函数是多态的。所以你可以像这样向 RHS 添加类型参数:
const apply1 : <X, Y>(f: F<X, Y>, x: X) => Y = <X, Y>(f: F<X, Y>, x: X): Y => f(x)
这应该可以修复错误。但此时,左侧的类型注释不再是必需的。所以你可以把它简化为
const apply1 = <X, Y>(f: F<X, Y>, x: X): Y => f(x)
进一步阅读
Avik Chaudhuri 在 similar stack overflow question, which in turn links to a similar answer on GitHub
上写了一个简短的解释
命名 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)
我需要从匿名 apply
函数的参数中对类型 F<X, Y>
的任何引用中删除泛型类型注释,类型检查器才能工作。
这是违反直觉的。
[编辑:]但似乎 Flow 能够键入检查 apply1
调用,即使它无法键入检查 apply1
本身:
apply1(x => x * 2, 'a') // error: ^ string. This type is incompatible with
apply1(x => x * 2, 1) // works
更一般地说:
// 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)
我必须从类型别名 Apply
的参数中删除泛型类型注释 X, Y
,以便 Flow 对其进行类型检查。
这是预期的行为还是我遗漏了什么?
TL;DR:尝试
const apply1 = <X, Y>(f: F<X, Y>, x: X): Y => f(x)
说明
首先,正如@squint 在评论中提到的,没有类型参数的 F
隐式意味着 F<any, any>
,这就是 apply0
在您的示例中有效的原因。
那为什么你的apply1
有错误呢?好吧,这是因为 Flow 不推断泛型。所以当你写
const apply1 : <X, Y>(f: F<X, Y>, x: X) => Y = (f, x) => f(x)
作业的右边是
(f, x) => f(x)
而且 Flow 不能推断出这个箭头函数是多态的。所以你可以像这样向 RHS 添加类型参数:
const apply1 : <X, Y>(f: F<X, Y>, x: X) => Y = <X, Y>(f: F<X, Y>, x: X): Y => f(x)
这应该可以修复错误。但此时,左侧的类型注释不再是必需的。所以你可以把它简化为
const apply1 = <X, Y>(f: F<X, Y>, x: X): Y => f(x)
进一步阅读
Avik Chaudhuri 在 similar stack overflow question, which in turn links to a similar answer on GitHub
上写了一个简短的解释