From dcca9d3cefadeb9ad6c2d7c2415fe1120a295dbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Koz=C5=82owski?= Date: Sun, 19 Mar 2023 00:13:10 +0100 Subject: [PATCH 1/3] support falsy and truthy literals simultanously --- .../src/rules/strict-boolean-expressions.ts | 15 +++--- .../rules/strict-boolean-expressions.test.ts | 46 +++++++++++++++++++ 2 files changed, 55 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 f1e8eacbdba..982e792fa96 100644 --- a/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts +++ b/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts @@ -835,10 +835,12 @@ export default util.createRule({ ); if (strings.length) { - if (strings.some(type => type.isStringLiteral() && type.value !== '')) { - variantTypes.add('truthy string'); - } else { + if ( + strings.some(type => !type.isStringLiteral() || type.value === '') + ) { variantTypes.add('string'); + } else { + variantTypes.add('truthy string'); } } @@ -848,11 +850,12 @@ export default util.createRule({ ts.TypeFlags.NumberLike | ts.TypeFlags.BigIntLike, ), ); + if (numbers.length) { - if (numbers.some(type => type.isNumberLiteral() && type.value !== 0)) { - variantTypes.add('truthy number'); - } else { + if (numbers.some(type => !type.isNumberLiteral() || type.value === 0)) { variantTypes.add('number'); + } else { + variantTypes.add('truthy number'); } } 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 388c2d4660f..cc4c7301489 100644 --- a/packages/eslint-plugin/tests/rules/strict-boolean-expressions.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-boolean-expressions.test.ts @@ -894,6 +894,7 @@ if (y) { declare const x: string | null; if (x) {} (x?: string) => !x; (x: T) => x ? 1 : 0; + function foo(x: '' | 'bar' | null) { if(!x) {} } `, errors: [ { @@ -956,6 +957,28 @@ if (y) { }, ], }, + { + messageId: 'conditionErrorNullableString', + line: 5, + column: 50, + suggestions: [ + { + messageId: 'conditionFixCompareNullish', + output: + " function foo(x: '' | 'bar' | null) { if(x == null) {} }", + }, + { + messageId: 'conditionFixDefaultEmptyString', + output: + " function foo(x: '' | 'bar' | null) { if(!(x ?? \"\")) {} }", + }, + { + messageId: 'conditionFixCastBoolean', + output: + " function foo(x: '' | 'bar' | null) { if(!Boolean(x)) {} }", + }, + ], + }, ], }), @@ -965,6 +988,7 @@ if (y) { declare const x: number | null; if (x) {} (x?: number) => !x; (x: T) => x ? 1 : 0; + function foo(x: 0 | 1 | null) { if(!x) {} } `, errors: [ { @@ -1027,6 +1051,28 @@ if (y) { }, ], }, + { + messageId: 'conditionErrorNullableNumber', + line: 5, + column: 45, + suggestions: [ + { + messageId: 'conditionFixCompareNullish', + output: + ' function foo(x: 0 | 1 | null) { if(x == null) {} }', + }, + { + messageId: 'conditionFixDefaultZero', + output: + ' function foo(x: 0 | 1 | null) { if(!(x ?? 0)) {} }', + }, + { + messageId: 'conditionFixCastBoolean', + output: + ' function foo(x: 0 | 1 | null) { if(!Boolean(x)) {} }', + }, + ], + }, ], }), From 3bb1bde0c81a16347f8e77afd596e1849e6ce4f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Koz=C5=82owski?= Date: Sun, 19 Mar 2023 12:36:36 +0100 Subject: [PATCH 2/3] replace Array.prototype.some condition with Array.prototype.every --- .../src/rules/strict-boolean-expressions.ts | 12 ++++++------ 1 file changed, 6 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 982e792fa96..dc6d09c75a6 100644 --- a/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts +++ b/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts @@ -836,11 +836,11 @@ export default util.createRule({ if (strings.length) { if ( - strings.some(type => !type.isStringLiteral() || type.value === '') + strings.every(type => type.isStringLiteral() && type.value !== '') ) { - variantTypes.add('string'); - } else { variantTypes.add('truthy string'); + } else { + variantTypes.add('string'); } } @@ -852,10 +852,10 @@ export default util.createRule({ ); if (numbers.length) { - if (numbers.some(type => !type.isNumberLiteral() || type.value === 0)) { - variantTypes.add('number'); - } else { + if (numbers.every(type => type.isNumberLiteral() && type.value !== 0)) { variantTypes.add('truthy number'); + } else { + variantTypes.add('number'); } } From ee4b83e9fecef339281d2d8a538027c5b0e3f22e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Koz=C5=82owski?= Date: Mon, 20 Mar 2023 12:24:50 +0100 Subject: [PATCH 3/3] format test cases to match prettier configuration --- .../rules/strict-boolean-expressions.test.ts | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) 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 cc4c7301489..1e33bae9889 100644 --- a/packages/eslint-plugin/tests/rules/strict-boolean-expressions.test.ts +++ b/packages/eslint-plugin/tests/rules/strict-boolean-expressions.test.ts @@ -894,7 +894,7 @@ if (y) { declare const x: string | null; if (x) {} (x?: string) => !x; (x: T) => x ? 1 : 0; - function foo(x: '' | 'bar' | null) { if(!x) {} } + function foo(x: '' | 'bar' | null) { if (!x) {} } `, errors: [ { @@ -960,22 +960,22 @@ if (y) { { messageId: 'conditionErrorNullableString', line: 5, - column: 50, + column: 51, suggestions: [ { messageId: 'conditionFixCompareNullish', output: - " function foo(x: '' | 'bar' | null) { if(x == null) {} }", + " function foo(x: '' | 'bar' | null) { if (x == null) {} }", }, { messageId: 'conditionFixDefaultEmptyString', output: - " function foo(x: '' | 'bar' | null) { if(!(x ?? \"\")) {} }", + " function foo(x: '' | 'bar' | null) { if (!(x ?? \"\")) {} }", }, { messageId: 'conditionFixCastBoolean', output: - " function foo(x: '' | 'bar' | null) { if(!Boolean(x)) {} }", + " function foo(x: '' | 'bar' | null) { if (!Boolean(x)) {} }", }, ], }, @@ -988,7 +988,7 @@ if (y) { declare const x: number | null; if (x) {} (x?: number) => !x; (x: T) => x ? 1 : 0; - function foo(x: 0 | 1 | null) { if(!x) {} } + function foo(x: 0 | 1 | null) { if (!x) {} } `, errors: [ { @@ -1054,22 +1054,22 @@ if (y) { { messageId: 'conditionErrorNullableNumber', line: 5, - column: 45, + column: 46, suggestions: [ { messageId: 'conditionFixCompareNullish', output: - ' function foo(x: 0 | 1 | null) { if(x == null) {} }', + ' function foo(x: 0 | 1 | null) { if (x == null) {} }', }, { messageId: 'conditionFixDefaultZero', output: - ' function foo(x: 0 | 1 | null) { if(!(x ?? 0)) {} }', + ' function foo(x: 0 | 1 | null) { if (!(x ?? 0)) {} }', }, { messageId: 'conditionFixCastBoolean', output: - ' function foo(x: 0 | 1 | null) { if(!Boolean(x)) {} }', + ' function foo(x: 0 | 1 | null) { if (!Boolean(x)) {} }', }, ], },