流程代码可以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');
}
这会导致流量错误:
type ObjectOfValues = {[string]:ValueType} ^ boolean . 此类型与someProperty的预期param类型不兼容:?string ^ string 2:type ObjectOfValues = {[string]:ValueType} ^ number . 此类型与9的预期参数类型不兼容:someProperty:?string ^ string
我究竟做错了什么?
1 回答
这段代码的问题在于对象是可变的,所以
getValueFromObjectOfValues
可以合法地做objectOfValues.someProperty = 5
.如果Flow允许这种子类型关系,那么原始调用者认为他们有一个
someProperty
类型为?string
的对象,现在会有一个someProperty
类型为number
的对象,从而破坏了类型系统 .要解决此问题,您可以使用property variance . 你需要像这样改变你的类型:
type ObjectOfValues = {+[string]: ValueType}
这意味着松散地,如果你有一个
ObjectOfValues
类型的对象,你所知道的是它的属性是ValueType
的某个子类型 . 这意味着当你从他们那里读取时,你会得到ValueType
. 但Flow知道他们实际上是什么类型 - 只是他们是ValueType
的子类型 .