0

我经常发现自己需要做以下事情,而 Flow 让它变得非常困难:

/* @flow */

type Foo = {
  +foo?: number,
}

type FooBar = {
  +foo?: number,
  +bar?: number,
}

const foo: Foo = {foo: 2}

function process(arg: $ReadOnly<FooBar>) {
}

process(foo)

有什么好的方法可以做到这一点吗?我收到以下错误:

17: process(foo)
            ^ Cannot call `process` with `foo` bound to `arg` because property `bar` is missing in `Foo` [1] but exists in `FooBar` [2].
References:
12: const foo: Foo = {foo: 2}
               ^ [1]
14: function process(arg: $ReadOnly<FooBar>) {
                                    ^ [2]
4

1 回答 1

1

Flow 默认为不精确的对象类型;这意味着,尽管Foo仅声明为显式具有单个(可选)类型属性foo,但类型number变量Foo理论上可以具有其他属性。例如,一个类型的变量Foo可以有一个属性bar。而且,由于bar没有输入Foobar的类型是不受限制的(即,不一定number)。因此,如果您要与arg.barin进行交互process并且 Flow 允许arg是 type Foo,则不能保证您正在与 a 进行交互number。因此,Flow 抱怨道。

解决此问题的一种方法是使用精确的对象类型。如果 Flow 知道类型变量Foo永远不会有bar属性,那么它可以安全地传递给process. 因此,您可以键入Foo

type Foo = {|
  +foo?: number,
|};

尝试流

(注意:对于$ReadOnly上述的定义,实用程序类型不是必需的,并且因为Foo的原始定义是不可写的。当然,保留它是可以的。)FooBarbar$ReadOnly

于 2019-06-04T21:21:13.920 回答