From 47c7be2811842fc6648d03015236a7841e28573b Mon Sep 17 00:00:00 2001 From: Cparros Date: Fri, 11 Nov 2022 14:59:22 -0700 Subject: [PATCH 1/2] chore(website): [prefer-nullish-coalescing] explicit notice for strictNullChecks --- .../eslint-plugin/docs/rules/prefer-nullish-coalescing.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/eslint-plugin/docs/rules/prefer-nullish-coalescing.md b/packages/eslint-plugin/docs/rules/prefer-nullish-coalescing.md index 5be277ecc73..d2fc95f4066 100644 --- a/packages/eslint-plugin/docs/rules/prefer-nullish-coalescing.md +++ b/packages/eslint-plugin/docs/rules/prefer-nullish-coalescing.md @@ -11,6 +11,10 @@ Because the nullish coalescing operator _only_ coalesces when the original value This rule reports when an `||` operator can be safely replaced with a `??`. +:::caution +This rule will not work as expected if [`strictNullChecks`](https://www.typescriptlang.org/tsconfig#strictNullChecks) is not enabled. +::: + ## Options ### `ignoreTernaryTests` From 3199c29dc4a1c7bc5a2854f2f577eaa2110090f1 Mon Sep 17 00:00:00 2001 From: Cparros Date: Sun, 4 Dec 2022 20:46:20 -0700 Subject: [PATCH 2/2] Added null check to prefer-nullish-coalescing along with a test. --- .../src/rules/prefer-nullish-coalescing.ts | 30 ++++++++++++++++++- .../rules/prefer-nullish-coalescing.test.ts | 20 +++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/packages/eslint-plugin/src/rules/prefer-nullish-coalescing.ts b/packages/eslint-plugin/src/rules/prefer-nullish-coalescing.ts index ca40160e982..14157427efa 100644 --- a/packages/eslint-plugin/src/rules/prefer-nullish-coalescing.ts +++ b/packages/eslint-plugin/src/rules/prefer-nullish-coalescing.ts @@ -1,5 +1,6 @@ import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES, AST_TOKEN_TYPES } from '@typescript-eslint/utils'; +import * as tsutils from 'tsutils'; import * as ts from 'typescript'; import * as util from '../util'; @@ -9,13 +10,15 @@ export type Options = [ ignoreConditionalTests?: boolean; ignoreTernaryTests?: boolean; ignoreMixedLogicalExpressions?: boolean; + allowRuleToRunWithoutStrictNullChecksIKnowWhatIAmDoing?: boolean; }, ]; export type MessageIds = | 'preferNullishOverOr' | 'preferNullishOverTernary' - | 'suggestNullish'; + | 'suggestNullish' + | 'noStrictNullCheck'; export default util.createRule({ name: 'prefer-nullish-coalescing', @@ -34,6 +37,8 @@ export default util.createRule({ preferNullishOverTernary: 'Prefer using nullish coalescing operator (`??`) instead of a ternary expression, as it is simpler to read.', suggestNullish: 'Fix to nullish coalescing operator (`??`).', + noStrictNullCheck: + 'This rule requires the `strictNullChecks` compiler option to be turned on to function correctly.', }, schema: [ { @@ -48,6 +53,9 @@ export default util.createRule({ ignoreMixedLogicalExpressions: { type: 'boolean', }, + allowRuleToRunWithoutStrictNullChecksIKnowWhatIAmDoing: { + type: 'boolean', + }, }, additionalProperties: false, }, @@ -58,6 +66,7 @@ export default util.createRule({ ignoreConditionalTests: true, ignoreTernaryTests: true, ignoreMixedLogicalExpressions: true, + allowRuleToRunWithoutStrictNullChecksIKnowWhatIAmDoing: false, }, ], create( @@ -67,12 +76,31 @@ export default util.createRule({ ignoreConditionalTests, ignoreTernaryTests, ignoreMixedLogicalExpressions, + allowRuleToRunWithoutStrictNullChecksIKnowWhatIAmDoing, }, ], ) { const parserServices = util.getParserServices(context); + const compilerOptions = parserServices.program.getCompilerOptions(); const sourceCode = context.getSourceCode(); const checker = parserServices.program.getTypeChecker(); + const isStrictNullChecks = tsutils.isStrictCompilerOptionEnabled( + compilerOptions, + 'strictNullChecks', + ); + + if ( + !isStrictNullChecks && + allowRuleToRunWithoutStrictNullChecksIKnowWhatIAmDoing !== true + ) { + context.report({ + loc: { + start: { line: 0, column: 0 }, + end: { line: 0, column: 0 }, + }, + messageId: 'noStrictNullCheck', + }); + } return { ConditionalExpression(node: TSESTree.ConditionalExpression): void { diff --git a/packages/eslint-plugin/tests/rules/prefer-nullish-coalescing.test.ts b/packages/eslint-plugin/tests/rules/prefer-nullish-coalescing.test.ts index 3824f464a58..49e50e741a8 100644 --- a/packages/eslint-plugin/tests/rules/prefer-nullish-coalescing.test.ts +++ b/packages/eslint-plugin/tests/rules/prefer-nullish-coalescing.test.ts @@ -1,4 +1,5 @@ import type { TSESLint } from '@typescript-eslint/utils'; +import * as path from 'path'; import type { MessageIds, @@ -385,6 +386,25 @@ x ?? y; ], })), + // noStrictNullCheck + { + code: ` +declare const x: string[] | null; +if (x) { +} + `, + errors: [ + { + messageId: 'noStrictNullCheck', + line: 0, + column: 1, + }, + ], + parserOptions: { + tsconfigRootDir: path.join(rootPath, 'unstrict'), + }, + }, + // ignoreConditionalTests ...nullishTypeInvalidTest((nullish, type) => ({ code: `