If you do
interface Foo {
bar: number | string
}
const buz: Foo = {
bar: 1,
};
you get
2: bar: number | string
^ string. This type is incompatible with
6: bar: 1,
^ number
But if you use type instead of interface you get no errors.
type Foo = {
bar: number | string
}
Is this expected behavior? If it is, why does this make sense? It seems reasonable to expect that interface behaves like type in this case.
Tested on https://flow.org/try/ against version 0.45.0 and master.
i think it's a bug, basically the problem is that
(({ bar: 1 }: { bar: number }): Foo); // not ok
(({ bar: 1 }: { bar: number | string }): Foo); // ok
afaik { bar: number } is a subtype of { bar: number | string }, so the first example should also work.
(as a workaround you can explicitly annotate the bar property in your object literal)
@madbence I'm always a bit confused on subtypes, but I think that { bar: number } is not a subtype of { bar: number | string }, but is a subtype of { +bar: number | string }. See this example
@futpib You'll also see that it will work with interface. I'm not sure that it means that the difference you spotted is not a bug (I don't know how interfaces work), but covariance might have something to do with that.
@AugustinLF Thanks a lot for your examples, they also made me look up docs more carefully. This is clearly intended and well-documented.
But still this bugs me a bit, at least in this example:
interface Invariant { property: number | string; }
var value1: Invariant = { property: 42 }; // Error!
function method1(value: Invariant) {
value.property = 3.14; // Works!
}
Why is writing a string | number property with number considered ok, but initializing it with number is not?
Now that it's clear that it's intended, might as well close the issue, but I guess it's also reasonable to leave it to a project member to decide.
You're getting the error because of variance problems. interface can be implemented by classes, so I think type vs interface makes a difference.
FWIW, this works:
interface Foo {
+bar: number | string
}
const buz: Foo = {
bar: 1,
};
Would be nice to get a statement from someone on the core team... Especially what @futpib has described is really weird.
Most helpful comment
Would be nice to get a statement from someone on the core team... Especially what @futpib has described is really weird.