在下面的代码中,我不明白为什么 Flow 会拒绝我的 kv
元组。
// @flow
type String = {
type: "string",
value: string
};
type Number = {
type: "number",
value: number
};
type Value = Number | String;
type Foo = { foo: "bar" } & Value;
let obj: Foo = {
foo: "bar",
type: "number",
value: 42
};
let kv: [string, Foo] = ["obj", obj];
Flow 似乎成功地进行了类型检查 obj
作为Foo
, 但不希望我在 [string, Foo]
中使用它元组。
确实我收到以下错误:
23: let kv: [string, Foo] = ["obj", obj];
^ intersection type. This type is incompatible with
15: type Foo = { foo: "bar" } & Value;
^ union: Number | String
这是怎么回事?
最佳答案
不幸的是,“Try Flow”没有为您提供完整的类型错误跟踪。如果你去here然后单击“json”,您可以深入了解并了解有关正在发生的事情的更多信息。
问题:非确定性
可以将其视为继承问题。 Flow 试图确定 Foo 是什么类型。因为在 Foo 的声明中没有指明它是 { foo } & Number 还是 { foo } & String,所以 Flow 似乎天真地尝试同时应用这两者。
所以在第 23 行,流程说,“类型不是 Foo,因为我希望属性“类型”是“字符串”,“值”是类型“数字”。但是如果你切换它, Flow 仍然会报错。
这是我思考问题的另一种方式:
class String
class Number
class Value extends String || Number // <= unable to determine what Foo is extending
type Foo = { stuff } & Value // <== ...locked-in non-deterministic
在这种情况下,Flow 无法确定“Foo”扩展的是什么,但如果某个变量被分配了 Value 类型,则有一些逻辑来解析类型。但是……
创建 Foo 别名时,Value 仍然是不确定的,就像 Flow 试图锁定 Foo 一样。一旦您访问某个属性,Flow 就会抛出错误。
幸运的是,有两种简单的方法可以解决这个问题。
不相交的联合
第一个涉及名为 disjoint unions 的功能. Here's a working example .
type Foo = { foo: "bar" }
type String = Foo & {
type: "string",
value: string
};
type Number = Foo & {
type: "number",
value: number
};
type Value = Number | String;
let obj: Foo = {
foo: "bar",
type: "number",
value: 42
};
let kv: [string, Foo] = ["obj", obj]; // no errors!
为什么会这样?同样,假设您使用继承模式编写此代码:
class Foo;
class String extends Foo; // <== deterministic
class Number extends Foo; // <== deterministic
var Value = String | Number // <== enum of certain classes, so still deterministic
对象类型传播(未发布)
如果您获取 Flow 的最新主分支,还会有一个很酷的功能,即对象类型传播。 Here's an example :
// @flow (master branch)
type String = {
type: "string",
value: string
};
type Number = {
type: "number",
value: number
};
type Value = Number | String;
type Foo = { foo: "bar", ...Value }
let obj: Foo = {
foo: "bar",
type: "number",
value: 42
}; // no error!
let otherObj: Foo = {
foo: "bar",
type: 'string',
value: 'I am a string',
}; // no error!
关于javascript - 为什么 Flow 拒绝由并集的交集组成的元组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42039969/