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
Conditional type narrowing ignores nullish coalescing to falsy value #43705
interfaceA{b?: B;}interfaceB{c: string;}(a: A): void=>{// Works, but intended behaviour is unclearif(a.b?.c)a.b.c.length;// Doesn't work 🙁if(a.b?.c??"")a.b.c.length;// ^ Object is possibly 'undefined'. ts(2532)// Not very concise 🙁if(a.b?.c!==undefined&&a.b.c)a.b.c.length;};
It's an edge case with a good use case. @typescript-eslint/strict-boolean-expressions helps avoid tricky bugs by requiring code to separately handle nullish vs. falsy values. Nullish coalescing would be the simplest way to explicitly treat nullish values the same as an empty string.
Why is if (a.b?.c) a.b.c.length unclear? When I see if (a.b?.c ?? "") or if (a.b?.c ?? false), I get very confused as to why something already falsey (null or undefined) would need to be coalesced to something else falsey in a conditional.
It doesn't seem like this particular lint rule configuration is helping code clarity (for humans or machines). If this turns out to be a popular thing to write we can see about adding detection for it but generally we don't spend perf budget on handling constructs that don't change the code behavior.
As an additional workaround, if (!!a.b?.c) seems like it would satisfy both your lint rule and our control flow analysis, though I’m generally in favor of turning off painful lint rules.
As an additional workaround, if (!!a.b?.c) seems like it would satisfy both your lint rule and our control flow analysis, though I’m generally in favor of turning off painful lint rules.
This is not testing only for null || undefined, but anything falsey. So the behavior changes.
Here is a simple code example that output an error in typescript, when it should not:
constreadProp=(property: string|undefined|null): string=>{if((property??undefined)===undefined){return''}returnproperty;// ~~~~~~~~// Type 'string | null | undefined' is not assignable to type 'string'.// Type 'undefined' is not assignable to type 'string'.}
Our Context:
We have a rule not to use null in our project, and writing the test like this avoid usage of null, while still checking in javascript against potential null values (that can happen due to external libraries).
Anyway, there is a problem in the type checking / type guard when using nullish coalescing operator "??".
FWIW, I long ago reconfigured our ESLint rules to use eqeqeq: ["error", "smart"] so that we could use the pattern if (a.b?.c != null) a.b.c.length. Works fine for us.
Activity
Zzzen commentedon Apr 16, 2021
why don't you use
if (a.b?.c != undefined) a.b.c.length;?andrewbranch commentedon Apr 16, 2021
Why is
if (a.b?.c) a.b.c.lengthunclear? When I seeif (a.b?.c ?? "")orif (a.b?.c ?? false), I get very confused as to why something already falsey (null or undefined) would need to be coalesced to something else falsey in a conditional.RyanCavanaugh commentedon Apr 19, 2021
It doesn't seem like this particular lint rule configuration is helping code clarity (for humans or machines). If this turns out to be a popular thing to write we can see about adding detection for it but generally we don't spend perf budget on handling constructs that don't change the code behavior.
andrewbranch commentedon Apr 19, 2021
As an additional workaround,
if (!!a.b?.c)seems like it would satisfy both your lint rule and our control flow analysis, though I’m generally in favor of turning off painful lint rules.aaronadamsCA commentedon Apr 20, 2021
I can change the use case, sure, but I wanted to point out the gap anyway. Never know when a little thing points to a bigger thing.
JeanRemiDelteil commentedon Dec 23, 2021
This is not testing only for
null || undefined, but anything falsey. So the behavior changes.Here is a simple code example that output an error in typescript, when it should not:
Playground link
Our Context:
We have a rule not to use
nullin our project, and writing the test like this avoid usage of null, while still checking in javascript against potential null values (that can happen due to external libraries).Anyway, there is a problem in the type checking / type guard when using nullish coalescing operator "??".
aaronadamsCA commentedon Dec 28, 2021
FWIW, I long ago reconfigured our ESLint rules to use
eqeqeq: ["error", "smart"]so that we could use the patternif (a.b?.c != null) a.b.c.length. Works fine for us.