Oved D
Oved D

Reputation: 7442

Flow - maybe type incompatible with union types

Flow code can be run here.

Using flow, I have a function that takes a key value pair object and gets a value for it - the value it gets should be a string, number or boolean.

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

I define some object type that has a property that's a maybe string:

type SomeValueWithNullableString = {
  someProperty: ?string
}

Then I create a function that takes my specific object type and calls the function to get a value from it:

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

This results in a flow error:

type ObjectOfValues = {[string]: ValueType} ^ boolean. This type is incompatible with the expected param type of someProperty: ?string ^ string 2: type ObjectOfValues = {[string]: ValueType} ^ number. This type is incompatible with the expected param type of 9: someProperty: ?string ^ string

What am I doing wrong?

Upvotes: 0

Views: 1245

Answers (1)

Nat Mote
Nat Mote

Reputation: 4086

The problem with this code is that the objects are mutable, so getValueFromObjectOfValues could legally do objectOfValues.someProperty = 5.

If Flow allowed this subtyping relationship, then the original caller, who thought they had an object where someProperty had type ?string, would now have an object where someProperty had type number, thereby breaking the type system.

To solve this problem, you can use property variance. You need to change your type like this:

type ObjectOfValues = {+[string]: ValueType}

This means, loosely, that if you have an object of type ObjectOfValues, all you know is that its properties are some subtype of ValueType. This means that when you read from them, you will get a ValueType. But Flow won't let you write to them, since it doesn't know what type they actually are -- just that they are a subtype of ValueType.

Upvotes: 2

Related Questions