为什么Flow不了解可空属性是否与非可空对象属性兼容?

时间:2018-02-14 09:48:31

标签: javascript flowtype refinement-type

我试图理解为什么流量抱怨两个非常相似的对象(try-flow-example)的属性之间不兼容:

/* @flow */
type Cow = {
  name: ?string
}

type NamedCow = {
  name: string
}

function foo (c: Cow): string {
  if (c.name == null) return 'anonymous'
  return c.name
}

const elsa: NamedCow = { name: 'Elsa' }

foo(elsa)

Flow使用上面的代码给出以下错误:

17: foo(elsa)
        ^ NamedCow. This type is incompatible with the expected param type of
10: function foo (c: Cow): string {
                     ^ Cow
    Property `name` is incompatible:
        7:   name: string
                   ^ string. This type is incompatible with
        3:   name: ?string
                   ^ null or undefined

为什么更具体的name: string与不太具体的name: ?string不兼容?由于NamedCow的name属性是Cow的name属性的子集,因此Cow不会对NamedCow的名称属性进行协变吗?

相关文档: Flow docs on subtypes

1 个答案:

答案 0 :(得分:2)

对象类型是不变的。这是因为可以读取和写入对象属性。

要了解为什么协方差不安全,请考虑将null分配给name函数中的属性foo的函数。

传递Cow类型:分配到name = null不会产生任何问题,因为name可以是?string

但是,如果您传递NamedCow类型,则name = null的分配将违反仅name的{​​{1}}类型。

您可以通过在string前加name作为协变来标注++name: ?string。这表示不会对其执行任何写入操作。这应该清除你目前看到的错误。 (属性方差修饰符为somewhat hidden in the docs