From 72c2e418a4180f6db5795ebb42cbc095f5c53c37 Mon Sep 17 00:00:00 2001 From: Taeheon Kim Date: Wed, 15 Dec 2021 16:01:01 +0900 Subject: [PATCH] fix(eslint-plugin): [strict-boolean-expression] false positive for truthy boolean (#4275) --- .../src/rules/strict-boolean-expressions.ts | 25 ++++++++++++++----- .../rules/strict-boolean-expressions.test.ts | 14 +++++++++++ 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts b/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts index 88ec00846f3..bf8d6709840 100644 --- a/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts +++ b/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts @@ -233,7 +233,7 @@ export default util.createRule({ wantedTypes.every(type => types.has(type)); // boolean - if (is('boolean')) { + if (is('boolean') || is('truthy boolean')) { // boolean is always okay return; } @@ -251,6 +251,11 @@ export default util.createRule({ return; } + // Known edge case: boolean `true` and nullish values are always valid boolean expressions + if (is('nullish', 'truthy boolean')) { + return; + } + // nullable boolean if (is('nullish', 'boolean')) { if (!options.allowNullableBoolean) { @@ -708,6 +713,7 @@ export default util.createRule({ type VariantType = | 'nullish' | 'boolean' + | 'truthy boolean' | 'string' | 'truthy string' | 'number' @@ -732,12 +738,19 @@ export default util.createRule({ ) { variantTypes.add('nullish'); } + const booleans = types.filter(type => + tsutils.isTypeFlagSet(type, ts.TypeFlags.BooleanLike), + ); - if ( - types.some(type => - tsutils.isTypeFlagSet(type, ts.TypeFlags.BooleanLike), - ) - ) { + // If incoming type is either "true" or "false", there will be one type + // object with intrinsicName set accordingly + // If incoming type is boolean, there will be two type objects with + // intrinsicName set "true" and "false" each because of tsutils.unionTypeParts() + if (booleans.length === 1) { + tsutils.isBooleanLiteralType(booleans[0], true) + ? variantTypes.add('truthy boolean') + : variantTypes.add('boolean'); + } else if (booleans.length === 2) { variantTypes.add('boolean'); } diff --git a/packages/eslint-plugin/tests/rules/strict-boolean-expressions.test.ts b/packages/eslint-plugin/tests/rules/strict-boolean-expressions.test.ts index c98102a1f17..335c2c71346 100644 --- a/packages/eslint-plugin/tests/rules/strict-boolean-expressions.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-boolean-expressions.test.ts @@ -167,6 +167,20 @@ function f(arg: 1 | null) { ` function f(arg: 1 | 2 | null) { if (arg) console.log(arg); +} + `, + ` +interface Options { + readonly enableSomething?: true; +} + +function f(opts: Options): void { + if (opts.enableSomething) console.log('Do something'); +} + `, + ` +declare const x: true | null; +if (x) { } `, {