流 - 可能类型与联合类型不兼容

时间:2017-06-13 20:18:53

标签: javascript flowtype

流程代码可以是run here.

使用flow,我有一个函数,它接受一个键值对象并为它获取一个值 - 它得到的值应该是一个字符串,数字或布尔值。

type ValueType =  string | number | bool | null | void;
type ObjectOfValues = {[string]: ValueType}
function getValueFromObjectOfValues(objectOfValues: ObjectOfValues, name: string): ValueType {
  return objectOfValues[name];
}

我定义了一个具有maybe字符串属性的对象类型:

type SomeValueWithNullableString = {
  someProperty: ?string
}

然后我创建一个函数,它接受我的特定对象类型并调用函数从中获取值:

function getValue (someObject: SomeValueWithNullableString) {
  return getValueFromObjectOfValues(someObject, 'someProperty');
}

这会导致流量错误:

  

输入ObjectOfValues = {[string]:ValueType}                                       ^布尔。此类型与someProperty的预期参数类型不兼容:   ?string ^ string 2:type ObjectOfValues =   {[string]:ValueType}                                       ^数字。此类型与9的预期参数类型不兼容:someProperty:   ?string ^ string

我做错了什么?

1 个答案:

答案 0 :(得分:1)

此代码的问题在于对象是可变的,因此getValueFromObjectOfValues可以合法地执行objectOfValues.someProperty = 5

如果Flow允许此子类型关系,那么原始调用者(他们认为他们有一个someProperty类型为?string的对象)现在会有一个someProperty类型为{number的对象1}},从而打破了类型系统。

要解决此问题,您可以使用property variance。您需要更改类型:

type ObjectOfValues = {+[string]: ValueType}

这意味着,如果你有ObjectOfValues类型的对象,那么你所知道的是它的属性是ValueType的某个子类型。这意味着当您从中读取时,您将获得ValueType。但Flow不会让你写信给他们,因为它不知道它们实际上是什么类型 - 只是它们是ValueType的子类型。