Description
Bug Report
🔎 Search Terms
typeof narrow, typeof discriminated union
🕗 Version & Regression Information
Affects all playground versions.
Please keep and fill in the line that best applies:
-->
- This is the behavior in every version I tried, and I reviewed the FAQ for entries mentioning "typeof" or "narrow". Closest is this https://github.com/Microsoft/TypeScript/wiki/FAQ#type-guards
The FAQ entry is TODO, but I don't think it applies here, the union is not &
'd with the type guard type at all.
⏯ Playground Link
Playground link with relevant code
💻 Code
const a = {} as {error: {a: string}, result: undefined} | { error:undefined, result: {b: number}}
let b: string;
let c:number;
if(typeof a.error !== 'undefined') {
b = a.error.a; // narrowed
} else {
c = a.result.b; // not narrowed
}
if(a.error !== undefined) {
b = a.error.a; // narrowed
} else {
c = a.result.b; // narrowed
}
A similar example that I also expected to work but actually fails for both cases:
https://www.typescriptlang.org/play?ts=4.8.0-beta#code/MYewdgzgLgBAhjAvDA3gX3hVBTATrkXALlThOlwEswBzNAGhl2wgFcAbKEsVgWwCM8MDAB9UMPAWIweAvI2ZtOJFP3JQqtNGgBQ7bLDUwK1GgG49BmMCKzBuC-tiUIAOT72kMABQAPEqxgANZgIADuYACUJL4wLjIeQogAfDBQAJ4ADtggAGYwsYhFMADkdnglFpS53hnZefAAdJKEMACExWWJuCWRqDowgzD8XnDN+ISNcGYwAPSzMnATYdgAJjoY2OwQ2P1D1qONihxQjfwz8zIgsGBLBCvrutXebS7ucrjeYy24kX0oAyGI2Q3wmuCmFwWt2Waw2Em2uwB+2Ah2OnDOkKuNzu4VhaCAA
const a = {} as {error: {a: string}, result: number } | { error: number, result: {b: string}}
let b: string;
let c:number;
let isNumber = (x: unknown): x is number => typeof x === 'number';
if(typeof a.error !== 'number') {
b = a.error.a; // narrowed
} else {
c = a.result.b; // not narrowed
}
if(!isNumber(a.error)) {
b = a.error.a; // narrowed
} else {
c = a.result.b; // not narrowed
}
🙁 Actual behavior
typeof based narrowing only narrowed one code flow branch.
🙂 Expected behavior
typeof based narrowing should narrow both sides of the branch.