Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhancement: [no-unnecessary-condition] flag when logical equality check has the same variable on either side #5076

Closed
4 tasks done
jguddas opened this issue May 25, 2022 · 3 comments
Labels
enhancement: plugin rule option New rule option for an existing eslint-plugin rule package: eslint-plugin Issues related to @typescript-eslint/eslint-plugin wontfix This will not be worked on

Comments

@jguddas
Copy link
Contributor

jguddas commented May 25, 2022

Before You File a Proposal Please Confirm You Have Done The Following...

My proposal is suitable for this project

  • I believe my proposal would be useful to the broader TypeScript community (meaning it is not a niche proposal).

Link to the rule's documentation

https://typescript-eslint.io/rules/no-unnecessary-condition/

Description

If the left and right side of a condition are the same, something has gone wrong.

Fail

a == a
a || a
a && a

Pass

true
a
a

Additional Info

No response

@jguddas jguddas added enhancement: plugin rule option New rule option for an existing eslint-plugin rule package: eslint-plugin Issues related to @typescript-eslint/eslint-plugin triage Waiting for maintainers to take a look labels May 25, 2022
@bradzacher
Copy link
Member

bradzacher commented May 25, 2022

If the left and right side of a condition are the same, something has gone wrong.

This is actually not always strictly correct!
EG: NaN. NaN === NaN always returns false, so doing x === x can be a way to test if a number variable has gone to NaN.
One could argue that Number.isNaN is better, for sure, but it is technically valid to use such a check to check for NaN.

The NaN case is why rules like no-constant-binary-expression and no-constant-condition do not error on this code.

I would accept a PR adding such a check to the lint rule which works like this:

  • for number, error and suggest changing the code to use Number.isNaN instead
  • for all other cases, error and suggest removing the check.

As for the logical expression side of things - no-unnecessary-condition already handles this to some degree.
Unfortunately due to a bug in our playground (#5079) I can't link it to you, but you can confirm that TS correctly refines the type of a inside the logical:
image

The only place this behaviour won't work is when TS is unable to refine out the truthy/falsey type (i.e. if the value is exactly string or number).

In the cases of string/number - I think it's getting to be too complicated for us to consider supporting in the lint rule. Logical expressions and understanding their AST is very complicated. For example:

b || a || a

It's obvious to us as humans that this is a duplicated condition, but based on the AST this is more difficult:

b || a || a
^^^^^^ LogicalExpression
^^^^^^^^^^^ LogicalExpression

I.e. the outer logical expression's left side is a logical expression whose right side matches the right side of the outer logical expression.
This can get even more complicated if you get into longer chains, eg:

a || b || c || a
^^^^^^ 
^^^^^^^^^^^
^^^^^^^^^^^^^^^^

The right of the outer logical expression is the same as the left of the logical expression on the left of logical expression the left logical expression.
If you start start mixing in && and ??, then you need to take care of precedence and the rules of logic, like:

a && b || a && c

the a is repeated here - and technically it could be rewritten as a && (b || c), but decyphering that from the AST is hard.

@bradzacher bradzacher added accepting prs Go ahead, send a pull request that resolves this issue and removed triage Waiting for maintainers to take a look labels May 25, 2022
@bradzacher bradzacher changed the title Enhancement: [no-unnecessary-condition] test if left and right are the same Enhancement: [no-unnecessary-condition] flag when logical equality check has the same variable on either side May 25, 2022
@jguddas
Copy link
Contributor Author

jguddas commented May 25, 2022

Hmm, seams quite complicated for not all that much benefit.

And we can't even safely support member expressions, something like x.x == x.x can be false 😞 .

let i = 0
const x = { get x() { return i++ } };
console.log (x.x == x.x); // logs false

@bradzacher
Copy link
Member

yeah it's a really dangerous thing!
we can definitely support identifiers, but otherwise it mightn't be worth doing anything here.
Given that code like a === a is super rare, I'm going to close this as no fix

@bradzacher bradzacher added wontfix This will not be worked on and removed accepting prs Go ahead, send a pull request that resolves this issue labels May 25, 2022
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jun 25, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement: plugin rule option New rule option for an existing eslint-plugin rule package: eslint-plugin Issues related to @typescript-eslint/eslint-plugin wontfix This will not be worked on
Projects
None yet
Development

No branches or pull requests

2 participants