Skip to content

fix(eslint-plugin): [no-unnecessary-boolean-literal-compare] preserve boolean result in fixer for nullable true comparisons#12365

Merged
JoshuaKGoldberg merged 15 commits into
typescript-eslint:mainfrom
paleite:feature/preserve-nullable-boolean-compare-fix
Jun 28, 2026
Merged

fix(eslint-plugin): [no-unnecessary-boolean-literal-compare] preserve boolean result in fixer for nullable true comparisons#12365
JoshuaKGoldberg merged 15 commits into
typescript-eslint:mainfrom
paleite:feature/preserve-nullable-boolean-compare-fix

Conversation

@paleite

@paleite paleite commented May 27, 2026

Copy link
Copy Markdown
Contributor

PR Checklist

Overview

This updates no-unnecessary-boolean-literal-compare, so autofixes for nullable boolean (e.g. boolean | null, boolean | null | undefined, boolean | undefined) comparisons to true keep returning boolean correctly. Previously, the autofixer was unsafe in value contexts, but correct in condition contexts.

Value contexts

This code snippet:

const isTrue = (x: boolean | undefined): boolean => x === true; // returns a `boolean`

was previously incorrectly autofixed to:

const isTrue = (x: boolean | undefined): boolean => x; // returns the same as the input (`boolean | undefined`) and causes a TypeScript error

That changed the returned value's type from boolean to boolean | undefined. The autofixer now preserves the boolean result:

const isTrue = (x: boolean | undefined): boolean => x ?? false; // returns a `boolean`

Condition contexts

This code snippet:

if (x === true) {}

was previously correctly autofixed to:

if (x) {}

This remains correct because condition contexts only care about truthiness, not about producing a boolean value.

I've included tests to ensure coverage and backwards compatibility.

@typescript-eslint

Copy link
Copy Markdown
Contributor

Thanks for the PR, @paleite!

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.

@netlify

netlify Bot commented May 27, 2026

Copy link
Copy Markdown

Deploy Preview for typescript-eslint ready!

Name Link
🔨 Latest commit cc76e2b
🔍 Latest deploy log https://app.netlify.com/projects/typescript-eslint/deploys/6a3cec34fb979b00077791b4
😎 Deploy Preview https://deploy-preview-12365--typescript-eslint.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
1 paths audited
Performance: 98 (🔴 down 1 from production)
Accessibility: 97 (no change from production)
Best Practices: 100 (no change from production)
SEO: 90 (no change from production)
PWA: 80 (no change from production)
View the detailed breakdown and full score reports
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@nx-cloud

nx-cloud Bot commented May 27, 2026

Copy link
Copy Markdown

View your CI Pipeline Execution ↗ for commit cc76e2b

Command Status Duration Result
nx run-many -t typecheck:tsgo ✅ Succeeded 1m 4s View ↗
nx run-many -t lint --projects=eslint-plugin --... ✅ Succeeded 59s View ↗
nx run-many -t lint --projects=typescript-estre... ✅ Succeeded 53s View ↗
nx run-many -t typecheck ✅ Succeeded 43s View ↗
nx run types:build ✅ Succeeded 1s View ↗
nx run-many -t lint --projects=parser,type-util... ✅ Succeeded 28s View ↗
nx run-many -t lint --projects=ast-spec,utils,s... ✅ Succeeded 28s View ↗
nx run integration-tests:test ✅ Succeeded 4s View ↗
Additional runs (12) ✅ Succeeded ... View ↗

💡 Verify your cache is correct by running tasks in a sandbox. Read docs ↗


☁️ Nx Cloud last updated this comment at 2026-06-25 08:55:58 UTC

@codecov

codecov Bot commented May 27, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 94.75%. Comparing base (54e2857) to head (cc76e2b).

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #12365      +/-   ##
==========================================
+ Coverage   87.00%   94.75%   +7.74%     
==========================================
  Files         513      223     -290     
  Lines       16570    11398    -5172     
  Branches     5175     3798    -1377     
==========================================
- Hits        14417    10800    -3617     
+ Misses       1463      254    -1209     
+ Partials      690      344     -346     
Flag Coverage Δ
unittest 94.75% <100.00%> (+7.74%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
...rc/rules/no-unnecessary-boolean-literal-compare.ts 100.00% <100.00%> (+4.44%) ⬆️
...lint-plugin/src/rules/prefer-nullish-coalescing.ts 95.87% <ø> (+0.55%) ⬆️
...ckages/eslint-plugin/src/util/isConditionalTest.ts 100.00% <100.00%> (ø)

... and 291 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Comment thread packages/eslint-plugin/src/rules/no-unnecessary-boolean-literal-compare.ts Outdated
@paleite paleite force-pushed the feature/preserve-nullable-boolean-compare-fix branch from 7e1459c to 3edd5a2 Compare May 28, 2026 08:15
@github-actions

Copy link
Copy Markdown

Hi @paleite, thanks for the update!

Just a quick heads-up: please try to avoid force-pushing moving forward. Rewriting history makes it harder for us to track incremental changes between reviews.

Since we squash merge anyway, there is no need to keep the commit history "clean" on this branch. Standard pushes are much preferred!

@paleite paleite marked this pull request as ready for review May 28, 2026 08:19
@paleite paleite requested a review from kirkwaiblinger May 28, 2026 08:19
@paleite paleite force-pushed the feature/preserve-nullable-boolean-compare-fix branch from 3edd5a2 to 5f94fdb Compare May 28, 2026 10:30
@github-actions

Copy link
Copy Markdown

Hi @paleite, thanks for the update!

Just a quick heads-up: please try to avoid force-pushing moving forward. Rewriting history makes it harder for us to track incremental changes between reviews.

Since we squash merge anyway, there is no need to keep the commit history "clean" on this branch. Standard pushes are much preferred!

@kirkwaiblinger kirkwaiblinger left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR @paleite!

I think that this PR does address the issue (and the tests look good to me), but some of the code is a little hard to follow, see comments. (note that it was already hard to follow, but I'd like to see if the added logic can be incorporated a bit better into the existing logic.

Also, would you please give the AI Contribution Policy a read and ensure that this PR (particularly the description) complies? Thanks!

Comment thread packages/eslint-plugin/src/rules/no-unnecessary-boolean-literal-compare.ts Outdated
Comment thread packages/eslint-plugin/src/rules/no-unnecessary-boolean-literal-compare.ts Outdated
Comment thread packages/eslint-plugin/src/rules/no-unnecessary-boolean-literal-compare.ts Outdated
@paleite

paleite commented Jun 11, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the PR @paleite!

I think that this PR does address the issue (and the tests look good to me), but some of the code is a little hard to follow, see comments. (note that it was already hard to follow, but I'd like to see if the added logic can be incorporated a bit better into the existing logic.

Also, would you please give the AI Contribution Policy a read and ensure that this PR (particularly the description) complies? Thanks!

Thanks for the review. I appreciate having another set of eyes looking at this. As per your request, I addressed (and resolved) the comments you had and rewrote the PR description, so it is now correctly aligned with the changes I did along the way, and it includes some more explanations. I've re-requested a review from you now.

@paleite paleite requested a review from kirkwaiblinger June 11, 2026 08:51
@kirkwaiblinger kirkwaiblinger changed the title fix(eslint-plugin): preserve boolean result for nullable true comparisons fix(eslint-plugin): [no-unnecessary-boolean-literal-compare] preserve boolean result for nullable true comparisons Jun 16, 2026
kirkwaiblinger
kirkwaiblinger previously approved these changes Jun 16, 2026

@kirkwaiblinger kirkwaiblinger left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made some tweaks to align with #12413, which ended up getting merged first.

Looks good to me! Thanks!

@kirkwaiblinger kirkwaiblinger added the 1 approval >=1 team member has approved this PR; we're now leaving it open for more reviews before we merge label Jun 16, 2026
@kirkwaiblinger kirkwaiblinger changed the title fix(eslint-plugin): [no-unnecessary-boolean-literal-compare] preserve boolean result for nullable true comparisons fix(eslint-plugin): [no-unnecessary-boolean-literal-compare] preserve boolean result in fixer for nullable true comparisons Jun 16, 2026
kirkwaiblinger
kirkwaiblinger previously approved these changes Jun 16, 2026
@paleite paleite requested a review from kirkwaiblinger June 16, 2026 09:29
@github-actions github-actions Bot removed the 1 approval >=1 team member has approved this PR; we're now leaving it open for more reviews before we merge label Jun 16, 2026
@paleite

paleite commented Jun 24, 2026

Copy link
Copy Markdown
Contributor Author

@kirkwaiblinger After the alignment, the coverage didn't pass anymore, so I improved it. Once you get some time, I'd appreciate a signoff, and then I'll merge it.

Thanks in advance!

@kirkwaiblinger kirkwaiblinger added the 1 approval >=1 team member has approved this PR; we're now leaving it open for more reviews before we merge label Jun 24, 2026
@JoshuaKGoldberg JoshuaKGoldberg merged commit 301f350 into typescript-eslint:main Jun 28, 2026
42 of 43 checks passed
@paleite paleite deleted the feature/preserve-nullable-boolean-compare-fix branch June 28, 2026 10:48
renovate Bot added a commit to andrei-picus-tink/auto-renovate that referenced this pull request Jul 1, 2026
| 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.
renovate Bot added a commit to andrei-picus-tink/auto-renovate that referenced this pull request Jul 4, 2026
| 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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

1 approval >=1 team member has approved this PR; we're now leaving it open for more reviews before we merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[no-unnecessary-boolean-literal-compare] Breaks type when using allowComparingNullableBooleansToTrue

3 participants