Open
Description
🔎 Search Terms
"exactoptionalpropertytypes union", "function call union assignability", "discriminated union assignment allowed incorrectly", "discriminated union assignable missing property"
🕗 Version & Regression Information
- This changed between versions 4.3.5 and 4.4.4
- still exists in nightly 5.9.0
⏯ Playground Link
💻 Code
export type U =
| {type: 'A'; value: null}
| {type: 'B'; value: string};
function call<T>(f: () => T): T {return f()}
export function functionCall(): U {
// should error but does not
return call(() => {
if (Math.random()) {
// not assignable to U (missing `value: null`)
return {type: 'A'};
}
return {type: 'B', value: 'test'};
});
}
export function directReturn(): U {
if (Math.random()) {
// Type '{ type: "A"; }' is not assignable to type 'U'.
// Property 'value' is missing in type '{ type: "A"; }' but required in type '{ type: "A"; value: null; }'.
return {type: 'A'};
}
return {type: 'B', value: 'test'};
}
🙁 Actual behavior
type error in directReturn
, but no type error in functionCall
🙂 Expected behavior
type error in both directReturn
and functionCall
, because {type: 'A'}
is not assignable to {type: 'A', value: null}
Additional information about the issue
It does work with exactOptionalPropertyTypes
disabled: Playground
With exactOptionalPropertyTypes
enabled, the return type of call()
is inferred as:
{
type: "A";
value?: never;
} | {
type: "B";
value: string;
}
whereas with it disabled, it's inferred as:
{
type: "A";
value?: undefined;
} | {
type: "B";
value: string;
}
But this doesn't fully explain it, because even assigning the result of call()
to a variable before returning it causes the expected error:
export function functionCall(): U {
const result = call(() => {
if (Math.random()) {
// not assignable to U (missing `value: null`)
return {type: 'A'};
}
return {type: 'B', value: 'test'};
});
// error as expected
return result;
}