流:形状类型和其他可选字段

时间:2019-06-04 14:30:13

标签: flowtype structural-typing

我经常发现自己需要执行以下操作,而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]

1 个答案:

答案 0 :(得分:1)

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

解决此问题的一种方法是使用精确的对象类型。如果Flow知道类型number的变量永远不会具有Foo属性,则可以安全地将其传递到bar中。因此,您可以将process输入为:

Foo

Try Flow

(注意:上面的type Foo = {| +foo?: number, |}; 定义和$ReadOnly的原始定义中,Foo实用程序类型不是必需的,因为FooBar是不可写的。 ,可以保留bar。)