I have a type which is a union of two object types, and they don't seem to be playing well:
const a: { x: string } | { y: number } = { y: 10 };
console.log(a.y); // Flow error: property not found in object type
console.log(a.x); // Flow error: property not found in object type
Am I doing something wrong?
You can only access fields that are present on all branches.
@vkurchatkin What can I do with the fields that are not present on all branches?
Well, before accessing them you need to known, which branch are you dealing with. This is only possible if branches don't intersect. For example, in your case, branches do intersect:
var example = {
x: 'foo',
y: 0
}
Here example has both types. The way to deal with this is to use disjoint union type:
const a: { t: 'x', x: string } | { t: 'y', y: number } = { t: 'y', y: 10 };
if (a.t === 'x') {
console.log(a.x);
} else {
console.log(a.y);
}
In this case property t is available on all branches, so you can check its value to refine the type.
I recently stumbled upon the same behavior which makes development harder. We're not going to introduce anchors in data structures to please Flow.
Flow can easily figure out the branch with simple check such as a.x or typeof(a.x) !== 'undefined'. The same way it works for unions of different types.
This expected behaviour. There is no guarantee about the type so you need to manually check it to avoid runtime errors. That's what type checker is about.
Here is a fixed version of the code in the original post:
https://flow.org/try/#0PTAEAEDMBsHsHcBQiDGsB2BnALqAhgFygDeoAHkTgE4CW6A5qAL6gA+JoAnkegK4C2AIwCmVZqAC8HbqACMABmYBuRDUgAKPADpOASlBossaMK1x6mnbpVrLZfYczHT5u9aA
Most helpful comment
I recently stumbled upon the same behavior which makes development harder. We're not going to introduce anchors in data structures to please Flow.
Flow can easily figure out the branch with simple check such as
a.xortypeof(a.x) !== 'undefined'. The same way it works for unions of different types.