Description
π Search Terms
"union type partial", "type union narrowing"
π Version & Regression Information
- This is the behavior in every version I tried, and I reviewed the FAQ for entries about Unions
β― Playground Link
π» Code
interface Foo {
foo: string;
}
interface Bar {
bar: number;
zaz: string;
}
function baz(props: Foo | Bar ) {
if ("bar" in props) {
console.log(props.zaz);
} else {
console.log(props.foo);
}
}
baz({ foo: "test" }); // test
baz({ bar: 1234, zaz: "yuh" }); // yuh
// oops! you can pass a subset of "both" rather than "one or the other".
baz({ foo: "test", bar: 123 }); // undefined
baz({ foo: "test", zaz: "dsfdf1" }); // test
π Actual behavior
I was surprised that I would pass in an object that is neither Foo
nor Bar
and TypeScript didn't complain about. This caused a bug at runtime that it seems like TypeScript should have caught?
Interestingly, the function definition is well aware that only one or the other could be passed. I could not write a scenario where that wasn't the case, but calling the funciton is where this fails.
π Expected behavior
I expected to be able to pass Foo
or Bar
but not both and certainly not neither.
Additional information about the issue
I couldn't find a previous version of TypeScript where this worked as I would expect it too. I was really wondering if I was doing something wrong or this was a well known issue, but I was struggling to find anything on the topic.
It looks like this also fails:
const data: Foo|Bar = {
foo: "test",
bar: 123,
};
in which case data
is neither Foo
nor Bar
but TypeScript doesn't complain about it.
You can see this with both of these that fail:
const data: Foo = {
foo: "test",
bar: 123,
};
const data: Bar = {
foo: "test",
bar: 123,
};
I would think that if they fail seperately, a union should also fail?