TypeScript Version: 3.5.0-dev.20190514
Search Terms: undefined discriminated union discriminant discriminator unions type guard control flow narrowing
Code
// --strictNullChecksinterfaceOption1{x: true;}interfaceOption2{x: false|undefined;}typeOptionUnion=Option1|Option2;functionacceptOption1(x: Option1): void{}functionacceptOption2(x: Option2): void{}functionacceptNever(x: never): void{}functiontest(anOption: OptionUnion): void{if(anOption.x===true){acceptOption1(anOption);}elseif(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:
// --strictNullCheckstypeOption1=true;typeOption2=false|undefined;typeOptionUnion=Option1|Option2;functionacceptOption1(x: Option1): void{}functionacceptOption2(x: Option2): void{}functionacceptNever(x: never): void{}functiontest(anOption: OptionUnion): void{if(anOption===true){acceptOption1(anOption);}elseif(anOption===false||anOption===undefined){acceptOption2(anOption);}else{acceptNever(anOption);// Not an error - correctly narrows to `never`}}Playground Link:
http://www.typescriptlang.org/play/index.html#src=%2F%2F%20--strictNullChecks%0D%0A%0D%0Ainterface%20Option1%20%7B%0D%0A%09x%3A%20true%3B%0D%0A%7D%0D%0A%0D%0Ainterface%20Option2%20%7B%0D%0A%09x%3A%20false%20%7C%20undefined%3B%0D%0A%7D%0D%0A%0D%0Atype%20OptionUnion%20%3D%20Option1%20%7C%20Option2%3B%0D%0A%0D%0Afunction%20acceptOption1(x%3A%20Option1)%3A%20void%20%7B%7D%0D%0A%0D%0Afunction%20acceptOption2(x%3A%20Option2)%3A%20void%20%7B%7D%0D%0A%0D%0Afunction%20acceptNever(x%3A%20never)%3A%20void%20%7B%7D%0D%0A%0D%0Afunction%20test(anOption%3A%20OptionUnion)%3A%20void%20%7B%0D%0A%09if%20(anOption.x%20%3D%3D%3D%20true)%20%7B%0D%0A%09%09acceptOption1(anOption)%3B%0D%0A%09%7D%20else%20if%20(anOption.x%20%3D%3D%3D%20false%20%7C%7C%20anOption.x%20%3D%3D%3D%20undefined)%20%7B%0D%0A%09%09acceptOption2(anOption)%3B%0D%0A%09%7D%20else%20%7B%0D%0A%09%09acceptNever(anOption)%3B%0D%0A%09%7D%0D%0A%7D%0D%0A
Related Issues:
#14471 is also using undefined as a discriminant, although the linked issue is restricting itself to talking about mapped types
TypeScript Version: 3.5.0-dev.20190514
Search Terms: undefined discriminated union discriminant discriminator unions type guard control flow narrowing
Code
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:
Playground Link:
http://www.typescriptlang.org/play/index.html#src=%2F%2F%20--strictNullChecks%0D%0A%0D%0Ainterface%20Option1%20%7B%0D%0A%09x%3A%20true%3B%0D%0A%7D%0D%0A%0D%0Ainterface%20Option2%20%7B%0D%0A%09x%3A%20false%20%7C%20undefined%3B%0D%0A%7D%0D%0A%0D%0Atype%20OptionUnion%20%3D%20Option1%20%7C%20Option2%3B%0D%0A%0D%0Afunction%20acceptOption1(x%3A%20Option1)%3A%20void%20%7B%7D%0D%0A%0D%0Afunction%20acceptOption2(x%3A%20Option2)%3A%20void%20%7B%7D%0D%0A%0D%0Afunction%20acceptNever(x%3A%20never)%3A%20void%20%7B%7D%0D%0A%0D%0Afunction%20test(anOption%3A%20OptionUnion)%3A%20void%20%7B%0D%0A%09if%20(anOption.x%20%3D%3D%3D%20true)%20%7B%0D%0A%09%09acceptOption1(anOption)%3B%0D%0A%09%7D%20else%20if%20(anOption.x%20%3D%3D%3D%20false%20%7C%7C%20anOption.x%20%3D%3D%3D%20undefined)%20%7B%0D%0A%09%09acceptOption2(anOption)%3B%0D%0A%09%7D%20else%20%7B%0D%0A%09%09acceptNever(anOption)%3B%0D%0A%09%7D%0D%0A%7D%0D%0A
Related Issues:
#14471 is also using
undefinedas a discriminant, although the linked issue is restricting itself to talking about mapped types