【发布时间】:2016-08-08 23:57:20
【问题描述】:
命名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 对其进行类型检查。
这是预期的行为还是我错过了什么?
【问题讨论】:
-
我不使用 Flow,也不是最熟悉泛型类型,但似乎所有
X和Y都应该分别对齐。此外,考虑到您的Apply类型确实有效,这个定义似乎应该失败:var res: String = apply((val) => 123, "abc"),但它通过了。 -
你说得对。正确键入检查的唯一定义
apply(x => x * 2, 'a')是命名函数版本。 -
我认为参数
f: F必须被视为f: F<Any, Any>其中Any是Flow 用来表示any 可能类型的任何内容。即使这样编译:var res: String = apply((val: Boolean) => 123, "abc")。可能需要提交报告。 -
我不确定 Flow 是基于哪种类型系统,但我猜这个问题与方差有关。
-
即使我们定义了显式类型
Apply<String, Number>,然后将字符串以外的东西传递给apply()的第二个参数it compiles。 ...但后来我正在修补一个我实际上还没有学过的类型系统,所以谁知道呢。帮我个忙,如果您有解决办法,请在此处留言。我很想知道结果如何。
标签: javascript flowtype