You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Type wrongly assumed to be undefined | number in this case聽#31603
Probably a design limitation because it requires narrowing the type of an expression (instead of a variable, or property), but just wanted to point out the obvious; you can restructure your code to work around it.
leta: number|undefined;letb: number|undefined;consttmp=a||b;if(tmp){constc=tmp;}
Although, it would be cool to have narrowing for side-effect free expressions. Not sure if there's much benefit to it.
I never use logical operators with non-boolean types, though.
Yeah, the problem is that a || b, from the compiler's point of view, doesn't prove anything individually about a or b, so it can't actually narrow them. At the time the assignment to c happens the types are still as follows:
a::number|undefinedb::number|undefined
So as far as the compiler is concerned, both could be undefined at the time the assignment to c happens. We know that's not the case since a || b requires at least one of them to be non-falsy, but the type narrowing mechanism isn't quite that nuanced. It doesn't track dependencies between variables--the same reason this doesn't work:
letx: number|undefinedletisNumber=typeofx==='number';if(isNumber){// x :: number | undefinedx+=1;// error}
Reacted by S. B. Tam, poseidonCore, Joe Calzaretta, Titian Cernicova-Dragomir, Lisiur Day, Kamran Ayub and Livio Brunner
interfaceTestInterface{value?: string;}functionfoo({ value }: TestInterface){constisValidValue=!!value&&/bar/.test(value);constthing=isValidValue ? value.split('x') : [];// ^ Object is possibly 'undefined'}
This is a simplified example of what we were trying within our code. "Clearly" if value is falsy, there's no way it would be undefined when checking isValidValue.
Activity
AnyhowStep commentedon May 26, 2019
Probably a design limitation because it requires narrowing the type of an expression (instead of a variable, or property), but just wanted to point out the obvious; you can restructure your code to work around it.
Although, it would be cool to have narrowing for side-effect free expressions. Not sure if there's much benefit to it.
I never use logical operators with non-boolean types, though.
fatcerberus commentedon May 26, 2019
Yeah, the problem is that
a || b, from the compiler's point of view, doesn't prove anything individually aboutaorb, so it can't actually narrow them. At the time the assignment tochappens the types are still as follows:So as far as the compiler is concerned, both could be
undefinedat the time the assignment tochappens. We know that's not the case sincea || brequires at least one of them to be non-falsy, but the type narrowing mechanism isn't quite that nuanced. It doesn't track dependencies between variables--the same reason this doesn't work:kamranayub commentedon Dec 20, 2019
I believe we just encountered this limitation and were scratching our heads:
Playground link
This is a simplified example of what we were trying within our code. "Clearly" if
valueis falsy, there's no way it would beundefinedwhen checkingisValidValue.