fix(eslint-plugin): [no-unnecessary-boolean-literal-compare] fix precedence bug in autofix#12413
Conversation
…edence bug in autofix
|
Thanks for the PR, @kirkwaiblinger! typescript-eslint is a 100% community driven project, and we are incredibly grateful that you are contributing to that community. The core maintainers work on this in their personal time, so please understand that it may not be possible for them to review your work immediately. Thanks again! 🙏 Please, if you or your company is finding typescript-eslint valuable, help us sustain the project by sponsoring it transparently on https://opencollective.com/typescript-eslint. |
✅ Deploy Preview for typescript-eslint ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
View your CI Pipeline Execution ↗ for commit e02b113
💡 Verify your cache is correct by running tasks in a sandbox. Read docs ↗ ☁️ Nx Cloud last updated this comment at |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #12413 +/- ##
==========================================
+ Coverage 86.99% 94.67% +7.68%
==========================================
Files 513 222 -291
Lines 16549 11378 -5171
Branches 5166 3788 -1378
==========================================
- Hits 14396 10772 -3624
+ Misses 1463 258 -1205
+ Partials 690 348 -342
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
| datasource | package | from | to | | ---------- | -------------------------------- | ------ | ------ | | npm | @typescript-eslint/eslint-plugin | 8.61.0 | 8.61.1 | | npm | @typescript-eslint/parser | 8.61.0 | 8.61.1 | ## [v8.61.1](https://github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#8611-2026-06-15) ##### 🩹 Fixes - **eslint-plugin:** \[no-unnecessary-template-expression] respect ECMAScript line terminators ([#12388](typescript-eslint/typescript-eslint#12388)) - **eslint-plugin:** \[no-unnecessary-boolean-literal-compare] fix precedence bug in autofix ([#12413](typescript-eslint/typescript-eslint#12413)) - **eslint-plugin:** \[no-unnecessary-type-assertion] wrap object literal in parens when removing TSTypeAssertion in arrow body ([#12394](typescript-eslint/typescript-eslint#12394), [#12393](typescript-eslint/typescript-eslint#12393)) - **eslint-plugin:** \[no-unnecessary-type-assertion] avoid false positive for template literal expressions ([#12281](typescript-eslint/typescript-eslint#12281)) - **eslint-plugin:** \[consistent-indexed-object-style] do not remove comments when fixing ([#12396](typescript-eslint/typescript-eslint#12396), [#10577](typescript-eslint/typescript-eslint#10577)) ##### ❤️ Thank You - Anas [@anasm266](https://github.com/anasm266) - Deftera [@Deftera186](https://github.com/Deftera186) - Kirk Waiblinger [@kirkwaiblinger](https://github.com/kirkwaiblinger) - lumir - Sarath Francis [@sarathfrancis90](https://github.com/sarathfrancis90) See [GitHub Releases](https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.61.1) for more information. You can read about our [versioning strategy](https://typescript-eslint.io/users/versioning) and [releases](https://typescript-eslint.io/users/releases) on our website.
| datasource | package | from | to | | ---------- | -------------------------------- | ------ | ------ | | npm | @typescript-eslint/eslint-plugin | 8.61.0 | 8.62.0 | | npm | @typescript-eslint/parser | 8.61.0 | 8.62.0 | ## [v8.62.0](https://github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#8620-2026-06-22) ##### 🚀 Features - remove redundant package.json "files" ([#12444](typescript-eslint/typescript-eslint#12444)) ##### ❤️ Thank You - Kirk Waiblinger [@kirkwaiblinger](https://github.com/kirkwaiblinger) See [GitHub Releases](https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.62.0) for more information. You can read about our [versioning strategy](https://typescript-eslint.io/users/versioning) and [releases](https://typescript-eslint.io/users/releases) on our website. ## [v8.61.1](https://github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#8611-2026-06-15) ##### 🩹 Fixes - **eslint-plugin:** \[no-unnecessary-template-expression] respect ECMAScript line terminators ([#12388](typescript-eslint/typescript-eslint#12388)) - **eslint-plugin:** \[no-unnecessary-boolean-literal-compare] fix precedence bug in autofix ([#12413](typescript-eslint/typescript-eslint#12413)) - **eslint-plugin:** \[no-unnecessary-type-assertion] wrap object literal in parens when removing TSTypeAssertion in arrow body ([#12394](typescript-eslint/typescript-eslint#12394), [#12393](typescript-eslint/typescript-eslint#12393)) - **eslint-plugin:** \[no-unnecessary-type-assertion] avoid false positive for template literal expressions ([#12281](typescript-eslint/typescript-eslint#12281)) - **eslint-plugin:** \[consistent-indexed-object-style] do not remove comments when fixing ([#12396](typescript-eslint/typescript-eslint#12396), [#10577](typescript-eslint/typescript-eslint#10577)) ##### ❤️ Thank You - Anas [@anasm266](https://github.com/anasm266) - Deftera [@Deftera186](https://github.com/Deftera186) - Kirk Waiblinger [@kirkwaiblinger](https://github.com/kirkwaiblinger) - lumir - Sarath Francis [@sarathfrancis90](https://github.com/sarathfrancis90) See [GitHub Releases](https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.61.1) for more information. You can read about our [versioning strategy](https://typescript-eslint.io/users/versioning) and [releases](https://typescript-eslint.io/users/releases) on our website.
| datasource | package | from | to | | ---------- | -------------------------------- | ------ | ------ | | npm | @typescript-eslint/eslint-plugin | 8.61.0 | 8.62.0 | | npm | @typescript-eslint/parser | 8.61.0 | 8.62.0 | ## [v8.62.0](https://github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#8620-2026-06-22) ##### 🚀 Features - remove redundant package.json "files" ([#12444](typescript-eslint/typescript-eslint#12444)) ##### ❤️ Thank You - Kirk Waiblinger [@kirkwaiblinger](https://github.com/kirkwaiblinger) See [GitHub Releases](https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.62.0) for more information. You can read about our [versioning strategy](https://typescript-eslint.io/users/versioning) and [releases](https://typescript-eslint.io/users/releases) on our website. ## [v8.61.1](https://github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#8611-2026-06-15) ##### 🩹 Fixes - **eslint-plugin:** \[no-unnecessary-template-expression] respect ECMAScript line terminators ([#12388](typescript-eslint/typescript-eslint#12388)) - **eslint-plugin:** \[no-unnecessary-boolean-literal-compare] fix precedence bug in autofix ([#12413](typescript-eslint/typescript-eslint#12413)) - **eslint-plugin:** \[no-unnecessary-type-assertion] wrap object literal in parens when removing TSTypeAssertion in arrow body ([#12394](typescript-eslint/typescript-eslint#12394), [#12393](typescript-eslint/typescript-eslint#12393)) - **eslint-plugin:** \[no-unnecessary-type-assertion] avoid false positive for template literal expressions ([#12281](typescript-eslint/typescript-eslint#12281)) - **eslint-plugin:** \[consistent-indexed-object-style] do not remove comments when fixing ([#12396](typescript-eslint/typescript-eslint#12396), [#10577](typescript-eslint/typescript-eslint#10577)) ##### ❤️ Thank You - Anas [@anasm266](https://github.com/anasm266) - Deftera [@Deftera186](https://github.com/Deftera186) - Kirk Waiblinger [@kirkwaiblinger](https://github.com/kirkwaiblinger) - lumir - Sarath Francis [@sarathfrancis90](https://github.com/sarathfrancis90) See [GitHub Releases](https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.61.1) for more information. You can read about our [versioning strategy](https://typescript-eslint.io/users/versioning) and [releases](https://typescript-eslint.io/users/releases) on our website.
| datasource | package | from | to | | ---------- | -------------------------------- | ------ | ------ | | npm | @typescript-eslint/eslint-plugin | 8.61.0 | 8.62.0 | | npm | @typescript-eslint/parser | 8.61.0 | 8.62.0 | ## [v8.62.0](https://github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#8620-2026-06-22) ##### 🚀 Features - remove redundant package.json "files" ([#12444](typescript-eslint/typescript-eslint#12444)) ##### ❤️ Thank You - Kirk Waiblinger [@kirkwaiblinger](https://github.com/kirkwaiblinger) See [GitHub Releases](https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.62.0) for more information. You can read about our [versioning strategy](https://typescript-eslint.io/users/versioning) and [releases](https://typescript-eslint.io/users/releases) on our website. ## [v8.61.1](https://github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#8611-2026-06-15) ##### 🩹 Fixes - **eslint-plugin:** \[no-unnecessary-template-expression] respect ECMAScript line terminators ([#12388](typescript-eslint/typescript-eslint#12388)) - **eslint-plugin:** \[no-unnecessary-boolean-literal-compare] fix precedence bug in autofix ([#12413](typescript-eslint/typescript-eslint#12413)) - **eslint-plugin:** \[no-unnecessary-type-assertion] wrap object literal in parens when removing TSTypeAssertion in arrow body ([#12394](typescript-eslint/typescript-eslint#12394), [#12393](typescript-eslint/typescript-eslint#12393)) - **eslint-plugin:** \[no-unnecessary-type-assertion] avoid false positive for template literal expressions ([#12281](typescript-eslint/typescript-eslint#12281)) - **eslint-plugin:** \[consistent-indexed-object-style] do not remove comments when fixing ([#12396](typescript-eslint/typescript-eslint#12396), [#10577](typescript-eslint/typescript-eslint#10577)) ##### ❤️ Thank You - Anas [@anasm266](https://github.com/anasm266) - Deftera [@Deftera186](https://github.com/Deftera186) - Kirk Waiblinger [@kirkwaiblinger](https://github.com/kirkwaiblinger) - lumir - Sarath Francis [@sarathfrancis90](https://github.com/sarathfrancis90) See [GitHub Releases](https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.61.1) for more information. You can read about our [versioning strategy](https://typescript-eslint.io/users/versioning) and [releases](https://typescript-eslint.io/users/releases) on our website.
| datasource | package | from | to | | ---------- | -------------------------------- | ------ | ------ | | npm | @typescript-eslint/eslint-plugin | 8.61.0 | 8.62.1 | | npm | @typescript-eslint/parser | 8.61.0 | 8.62.1 | ## [v8.62.1](https://github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#8621-2026-06-29) ##### 🩹 Fixes - **eslint-plugin:** \[no-unnecessary-type-assertion] parenthesize object literal at left edge of expression statement ([#12443](typescript-eslint/typescript-eslint#12443), [#12418](typescript-eslint/typescript-eslint#12418)) - **eslint-plugin:** \[no-unnecessary-boolean-literal-compare] preserve boolean result in fixer for nullable true comparisons ([#12365](typescript-eslint/typescript-eslint#12365)) - **eslint-plugin:** \[prefer-optional-chain] use suggestion instead of autofix for trailing binary operator ([#12328](typescript-eslint/typescript-eslint#12328)) ##### ❤️ Thank You - Kirk Waiblinger [@kirkwaiblinger](https://github.com/kirkwaiblinger) - mdm317 - Patrick Aleite - 송재욱 See [GitHub Releases](https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.62.1) for more information. You can read about our [versioning strategy](https://typescript-eslint.io/users/versioning) and [releases](https://typescript-eslint.io/users/releases) on our website. ## [v8.62.0](https://github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#8620-2026-06-22) ##### 🚀 Features - remove redundant package.json "files" ([#12444](typescript-eslint/typescript-eslint#12444)) ##### ❤️ Thank You - Kirk Waiblinger [@kirkwaiblinger](https://github.com/kirkwaiblinger) See [GitHub Releases](https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.62.0) for more information. You can read about our [versioning strategy](https://typescript-eslint.io/users/versioning) and [releases](https://typescript-eslint.io/users/releases) on our website. ## [v8.61.1](https://github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#8611-2026-06-15) ##### 🩹 Fixes - **eslint-plugin:** \[no-unnecessary-template-expression] respect ECMAScript line terminators ([#12388](typescript-eslint/typescript-eslint#12388)) - **eslint-plugin:** \[no-unnecessary-boolean-literal-compare] fix precedence bug in autofix ([#12413](typescript-eslint/typescript-eslint#12413)) - **eslint-plugin:** \[no-unnecessary-type-assertion] wrap object literal in parens when removing TSTypeAssertion in arrow body ([#12394](typescript-eslint/typescript-eslint#12394), [#12393](typescript-eslint/typescript-eslint#12393)) - **eslint-plugin:** \[no-unnecessary-type-assertion] avoid false positive for template literal expressions ([#12281](typescript-eslint/typescript-eslint#12281)) - **eslint-plugin:** \[consistent-indexed-object-style] do not remove comments when fixing ([#12396](typescript-eslint/typescript-eslint#12396), [#10577](typescript-eslint/typescript-eslint#10577)) ##### ❤️ Thank You - Anas [@anasm266](https://github.com/anasm266) - Deftera [@Deftera186](https://github.com/Deftera186) - Kirk Waiblinger [@kirkwaiblinger](https://github.com/kirkwaiblinger) - lumir - Sarath Francis [@sarathfrancis90](https://github.com/sarathfrancis90) See [GitHub Releases](https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.61.1) for more information. You can read about our [versioning strategy](https://typescript-eslint.io/users/versioning) and [releases](https://typescript-eslint.io/users/releases) on our website.
| datasource | package | from | to | | ---------- | -------------------------------- | ------ | ------ | | npm | @typescript-eslint/eslint-plugin | 8.61.0 | 8.62.1 | | npm | @typescript-eslint/parser | 8.61.0 | 8.62.1 | ## [v8.62.1](https://github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#8621-2026-06-29) ##### 🩹 Fixes - **eslint-plugin:** \[no-unnecessary-type-assertion] parenthesize object literal at left edge of expression statement ([#12443](typescript-eslint/typescript-eslint#12443), [#12418](typescript-eslint/typescript-eslint#12418)) - **eslint-plugin:** \[no-unnecessary-boolean-literal-compare] preserve boolean result in fixer for nullable true comparisons ([#12365](typescript-eslint/typescript-eslint#12365)) - **eslint-plugin:** \[prefer-optional-chain] use suggestion instead of autofix for trailing binary operator ([#12328](typescript-eslint/typescript-eslint#12328)) ##### ❤️ Thank You - Kirk Waiblinger [@kirkwaiblinger](https://github.com/kirkwaiblinger) - mdm317 - Patrick Aleite - 송재욱 See [GitHub Releases](https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.62.1) for more information. You can read about our [versioning strategy](https://typescript-eslint.io/users/versioning) and [releases](https://typescript-eslint.io/users/releases) on our website. ## [v8.62.0](https://github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#8620-2026-06-22) ##### 🚀 Features - remove redundant package.json "files" ([#12444](typescript-eslint/typescript-eslint#12444)) ##### ❤️ Thank You - Kirk Waiblinger [@kirkwaiblinger](https://github.com/kirkwaiblinger) See [GitHub Releases](https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.62.0) for more information. You can read about our [versioning strategy](https://typescript-eslint.io/users/versioning) and [releases](https://typescript-eslint.io/users/releases) on our website. ## [v8.61.1](https://github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#8611-2026-06-15) ##### 🩹 Fixes - **eslint-plugin:** \[no-unnecessary-template-expression] respect ECMAScript line terminators ([#12388](typescript-eslint/typescript-eslint#12388)) - **eslint-plugin:** \[no-unnecessary-boolean-literal-compare] fix precedence bug in autofix ([#12413](typescript-eslint/typescript-eslint#12413)) - **eslint-plugin:** \[no-unnecessary-type-assertion] wrap object literal in parens when removing TSTypeAssertion in arrow body ([#12394](typescript-eslint/typescript-eslint#12394), [#12393](typescript-eslint/typescript-eslint#12393)) - **eslint-plugin:** \[no-unnecessary-type-assertion] avoid false positive for template literal expressions ([#12281](typescript-eslint/typescript-eslint#12281)) - **eslint-plugin:** \[consistent-indexed-object-style] do not remove comments when fixing ([#12396](typescript-eslint/typescript-eslint#12396), [#10577](typescript-eslint/typescript-eslint#10577)) ##### ❤️ Thank You - Anas [@anasm266](https://github.com/anasm266) - Deftera [@Deftera186](https://github.com/Deftera186) - Kirk Waiblinger [@kirkwaiblinger](https://github.com/kirkwaiblinger) - lumir - Sarath Francis [@sarathfrancis90](https://github.com/sarathfrancis90) See [GitHub Releases](https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.61.1) for more information. You can read about our [versioning strategy](https://typescript-eslint.io/users/versioning) and [releases](https://typescript-eslint.io/users/releases) on our website.

PR Checklist
Overview
Took an opportunity to refactor the fixer a bit. The fixer previously operated by
This was rather confusing to me, since it's highly dependent on the order in which ESLint processes insertions/appends to the same location. I reworked it to just build up the replacement string itself and then replace the mutated node, without touching it afterwards.
I also had a hard time making sense of the boolean conditions in the fixer. I simplified these down to just "does the overall comparison have negated truthiness compared to the original value?" and "do we need to flip the truth table of the nullish cases?"
Lastly, refactored
comparison.booleanLiteralInComparisonwith typebooleantocomparison.booleanLiteralwith type"true" | "false". The second way makes it clear that it's a value rather than a condition.With the above in place, the fundamental fix is to detect if something like
expression === truehas been replaced with justexpressionand put parentheses if the surroundings require it. This has been achieved by tracking whether the current state of the replacement text being built up is a strong precedence node or not, and, if at the end, parentheses are needed, adding a pair.