我试图理解为什么流量抱怨两个非常相似的对象(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
答案 0 :(得分:2)
对象类型是不变的。这是因为可以读取和写入对象属性。
要了解为什么协方差不安全,请考虑将null
分配给name
函数中的属性foo
的函数。
传递Cow
类型:分配到name = null
不会产生任何问题,因为name
可以是?string
。
但是,如果您传递NamedCow
类型,则name = null
的分配将违反仅name
的{{1}}类型。
您可以通过在string
前加name
作为协变来标注+
。+name: ?string
。这表示不会对其执行任何写入操作。这应该清除你目前看到的错误。 (属性方差修饰符为somewhat hidden in the docs)