diff --git a/packages/eslint-plugin/docs/rules/no-unnecessary-boolean-literal-compare.mdx b/packages/eslint-plugin/docs/rules/no-unnecessary-boolean-literal-compare.mdx index 16462771e768..3562b8d09c91 100644 --- a/packages/eslint-plugin/docs/rules/no-unnecessary-boolean-literal-compare.mdx +++ b/packages/eslint-plugin/docs/rules/no-unnecessary-boolean-literal-compare.mdx @@ -129,6 +129,22 @@ if (someNullCondition ?? true) { +### `allowRuleToRunWithoutStrictNullChecksIKnowWhatIAmDoing` + +:::danger Deprecated + +This option will be removed in the next major version of typescript-eslint. + +::: + +{/* insert option description */} + +Without `strictNullChecks`, TypeScript essentially erases `undefined` and `null` from the types. This means when this rule inspects the types from a variable, **it will not be able to tell that the variable might be `null` or `undefined`**, which essentially makes this rule useless. + +You should be using `strictNullChecks` to ensure complete type-safety in your codebase. + +If for some reason you cannot turn on `strictNullChecks`, but still want to use this rule - you can use this option to allow it - but know that the behavior of this rule is _undefined_ with the compiler option turned off. We will not accept bug reports if you are using this option. + ## Fixer | Comparison | Fixer Output | Notes | diff --git a/packages/eslint-plugin/src/rules/no-unnecessary-boolean-literal-compare.ts b/packages/eslint-plugin/src/rules/no-unnecessary-boolean-literal-compare.ts index dde39ccc223f..d5ed0974ecce 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-boolean-literal-compare.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-boolean-literal-compare.ts @@ -16,12 +16,14 @@ export type MessageIds = | 'comparingNullableToTrueDirect' | 'comparingNullableToTrueNegated' | 'direct' - | 'negated'; + | 'negated' + | 'noStrictNullCheck'; export type Options = [ { allowComparingNullableBooleansToFalse?: boolean; allowComparingNullableBooleansToTrue?: boolean; + allowRuleToRunWithoutStrictNullChecksIKnowWhatIAmDoing?: boolean; }, ]; @@ -57,6 +59,8 @@ export default createRule({ 'This expression unnecessarily compares a boolean value to a boolean instead of using it directly.', negated: 'This expression unnecessarily compares a boolean value to a boolean instead of negating it.', + noStrictNullCheck: + 'This rule requires the `strictNullChecks` compiler option to be turned on to function correctly.', }, schema: [ { @@ -73,6 +77,11 @@ export default createRule({ description: 'Whether to allow comparisons between nullable boolean variables and `true`.', }, + allowRuleToRunWithoutStrictNullChecksIKnowWhatIAmDoing: { + type: 'boolean', + description: + 'Unless this is set to `true`, the rule will error on every file whose `tsconfig.json` does _not_ have the `strictNullChecks` compiler option (or `strict`) set to `true`.', + }, }, }, ], @@ -81,11 +90,31 @@ export default createRule({ { allowComparingNullableBooleansToFalse: true, allowComparingNullableBooleansToTrue: true, + allowRuleToRunWithoutStrictNullChecksIKnowWhatIAmDoing: false, }, ], create(context, [options]) { const services = getParserServices(context); const checker = services.program.getTypeChecker(); + const compilerOptions = services.program.getCompilerOptions(); + + const isStrictNullChecks = tsutils.isStrictCompilerOptionEnabled( + compilerOptions, + 'strictNullChecks', + ); + + if ( + !isStrictNullChecks && + options.allowRuleToRunWithoutStrictNullChecksIKnowWhatIAmDoing !== true + ) { + context.report({ + loc: { + start: { column: 0, line: 0 }, + end: { column: 0, line: 0 }, + }, + messageId: 'noStrictNullCheck', + }); + } function getBooleanComparison( node: TSESTree.BinaryExpression, diff --git a/packages/eslint-plugin/tests/docs.test.ts b/packages/eslint-plugin/tests/docs.test.ts index 412250206d14..89e499e38e58 100644 --- a/packages/eslint-plugin/tests/docs.test.ts +++ b/packages/eslint-plugin/tests/docs.test.ts @@ -201,6 +201,7 @@ describe('Validating rule docs', () => { 'switch-exhaustiveness-check', 'switch-exhaustiveness-check', 'unbound-method', + 'no-unnecessary-boolean-literal-compare', ]); it('All rules must have a corresponding rule doc', () => { diff --git a/packages/eslint-plugin/tests/rules/no-unnecessary-boolean-literal-compare.test.ts b/packages/eslint-plugin/tests/rules/no-unnecessary-boolean-literal-compare.test.ts index 77d395aeb4d1..ef3107357a77 100644 --- a/packages/eslint-plugin/tests/rules/no-unnecessary-boolean-literal-compare.test.ts +++ b/packages/eslint-plugin/tests/rules/no-unnecessary-boolean-literal-compare.test.ts @@ -1,4 +1,5 @@ import { noFormat, RuleTester } from '@typescript-eslint/rule-tester'; +import * as path from 'node:path'; import rule from '../../src/rules/no-unnecessary-boolean-literal-compare'; import { getFixturesRootDir } from '../RuleTester'; @@ -123,6 +124,24 @@ const extendsUnknown: ( } }; `, + { + code: ` +function test(a?: boolean): boolean { + // eslint-disable-next-line + return a !== false; +} + `, + languageOptions: { + parserOptions: { + tsconfigRootDir: path.join(rootDir, 'unstrict'), + }, + }, + options: [ + { + allowRuleToRunWithoutStrictNullChecksIKnowWhatIAmDoing: true, + }, + ], + }, ], invalid: [ @@ -586,5 +605,25 @@ const extendsUnknown: ( }; `, }, + { + code: ` +function foo(): boolean {} + `, + errors: [ + { + messageId: 'noStrictNullCheck', + }, + ], + languageOptions: { + parserOptions: { + tsconfigRootDir: path.join(rootDir, 'unstrict'), + }, + }, + options: [ + { + allowRuleToRunWithoutStrictNullChecksIKnowWhatIAmDoing: false, + }, + ], + }, ], }); diff --git a/packages/eslint-plugin/tests/schema-snapshots/no-unnecessary-boolean-literal-compare.shot b/packages/eslint-plugin/tests/schema-snapshots/no-unnecessary-boolean-literal-compare.shot index faf2bf9e1822..4072b4f40e53 100644 --- a/packages/eslint-plugin/tests/schema-snapshots/no-unnecessary-boolean-literal-compare.shot +++ b/packages/eslint-plugin/tests/schema-snapshots/no-unnecessary-boolean-literal-compare.shot @@ -15,6 +15,10 @@ exports[`Rule schemas should be convertible to TS types for documentation purpos "allowComparingNullableBooleansToTrue": { "description": "Whether to allow comparisons between nullable boolean variables and \`true\`.", "type": "boolean" + }, + "allowRuleToRunWithoutStrictNullChecksIKnowWhatIAmDoing": { + "description": "Unless this is set to \`true\`, the rule will error on every file whose \`tsconfig.json\` does _not_ have the \`strictNullChecks\` compiler option (or \`strict\`) set to \`true\`.", + "type": "boolean" } }, "type": "object" @@ -30,6 +34,8 @@ type Options = [ allowComparingNullableBooleansToFalse?: boolean; /** Whether to allow comparisons between nullable boolean variables and \`true\`. */ allowComparingNullableBooleansToTrue?: boolean; + /** Unless this is set to \`true\`, the rule will error on every file whose \`tsconfig.json\` does _not_ have the \`strictNullChecks\` compiler option (or \`strict\`) set to \`true\`. */ + allowRuleToRunWithoutStrictNullChecksIKnowWhatIAmDoing?: boolean; }, ]; " pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy