From 2cda91f1c55d5995c6316621c5ca02cd69406680 Mon Sep 17 00:00:00 2001 From: Joshua Chen Date: Thu, 9 Mar 2023 22:19:47 -0500 Subject: [PATCH] feat(eslint-plugin): [no-unnecessary-cond] check logical assignments --- .../src/rules/no-unnecessary-condition.ts | 13 ++ .../rules/no-unnecessary-condition.test.ts | 117 ++++++++++++++++++ 2 files changed, 130 insertions(+) diff --git a/packages/eslint-plugin/src/rules/no-unnecessary-condition.ts b/packages/eslint-plugin/src/rules/no-unnecessary-condition.ts index 4951e281af4e..6af9bc0e9e09 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-condition.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-condition.ts @@ -636,7 +636,20 @@ export default createRule({ checkOptionalChain(node, node.callee, ''); } + function checkAssignmentExpression( + node: TSESTree.AssignmentExpression, + ): void { + // Similar to checkLogicalExpressionForUnnecessaryConditionals, since + // a ||= b is equivalent to a || (a = b) + if (['||=', '&&='].includes(node.operator)) { + checkNode(node.left); + } else if (node.operator === '??=') { + checkNodeForNullish(node.left); + } + } + return { + AssignmentExpression: checkAssignmentExpression, BinaryExpression: checkIfBinaryExpressionIsNecessaryConditional, CallExpression: checkCallExpression, ConditionalExpression: (node): void => checkNode(node.test), diff --git a/packages/eslint-plugin/tests/rules/no-unnecessary-condition.test.ts b/packages/eslint-plugin/tests/rules/no-unnecessary-condition.test.ts index 96cad00c908b..e3647102305b 100644 --- a/packages/eslint-plugin/tests/rules/no-unnecessary-condition.test.ts +++ b/packages/eslint-plugin/tests/rules/no-unnecessary-condition.test.ts @@ -548,6 +548,18 @@ interface Foo { type OptionalFoo = Foo | undefined; declare const foo: OptionalFoo; foo?.[1]?.length; + `, + ` +declare let foo: number | null; +foo ??= 1; + `, + ` +declare let foo: number; +foo ||= 1; + `, + ` +declare let foo: number; +foo &&= 1; `, // https://github.com/typescript-eslint/typescript-eslint/issues/6264 ` @@ -1676,5 +1688,110 @@ function getElem(dict: Record, key: string) { }, ], }, + { + code: ` +declare let foo: {}; +foo ??= 1; + `, + errors: [ + { + messageId: 'neverNullish', + line: 3, + endLine: 3, + column: 1, + endColumn: 4, + }, + ], + }, + { + code: ` +declare let foo: number; +foo ??= 1; + `, + errors: [ + { + messageId: 'neverNullish', + line: 3, + endLine: 3, + column: 1, + endColumn: 4, + }, + ], + }, + { + code: ` +declare let foo: null; +foo ??= null; + `, + errors: [ + { + messageId: 'alwaysNullish', + line: 3, + endLine: 3, + column: 1, + endColumn: 4, + }, + ], + }, + { + code: ` +declare let foo: {}; +foo ||= 1; + `, + errors: [ + { + messageId: 'alwaysTruthy', + line: 3, + endLine: 3, + column: 1, + endColumn: 4, + }, + ], + }, + { + code: ` +declare let foo: null; +foo ||= null; + `, + errors: [ + { + messageId: 'alwaysFalsy', + line: 3, + endLine: 3, + column: 1, + endColumn: 4, + }, + ], + }, + { + code: ` +declare let foo: {}; +foo &&= 1; + `, + errors: [ + { + messageId: 'alwaysTruthy', + line: 3, + endLine: 3, + column: 1, + endColumn: 4, + }, + ], + }, + { + code: ` +declare let foo: null; +foo &&= null; + `, + errors: [ + { + messageId: 'alwaysFalsy', + line: 3, + endLine: 3, + column: 1, + endColumn: 4, + }, + ], + }, ], });