Closed
Description
TypeScript Version: 3.5.0-dev.20190514
Search Terms: undefined discriminated union discriminant discriminator unions type guard control flow narrowing
Code
// --strictNullChecks
interface Option1 {
x: true;
}
interface Option2 {
x: false | undefined;
}
type OptionUnion = Option1 | Option2;
function acceptOption1(x: Option1): void {}
function acceptOption2(x: Option2): void {}
function acceptNever(x: never): void {}
function test(anOption: OptionUnion): void {
if (anOption.x === true) {
acceptOption1(anOption);
} else if (anOption.x === false || anOption.x === undefined) {
acceptOption2(anOption);
} else {
acceptNever(anOption);
}
}
Expected behavior:
No errors.
Actual behavior:
acceptNever(anOption);
has an error: Argument of type 'Option2' is not assignable to parameter of type 'never'. ts(2345)
Note that the code works correctly if the discriminator is not a property:
// --strictNullChecks
type Option1 = true;
type Option2 = false | undefined;
type OptionUnion = Option1 | Option2;
function acceptOption1(x: Option1): void {}
function acceptOption2(x: Option2): void {}
function acceptNever(x: never): void {}
function test(anOption: OptionUnion): void {
if (anOption === true) {
acceptOption1(anOption);
} else if (anOption === false || anOption === undefined) {
acceptOption2(anOption);
} else {
acceptNever(anOption); // Not an error - correctly narrows to `never`
}
}
Playground Link:
Related Issues:
#14471 is also using undefined
as a discriminant, although the linked issue is restricting itself to talking about mapped types