Skip to content

Commit

Permalink
fix(eslint-plugin): [no-unnecessary-condition] better handling for un…
Browse files Browse the repository at this point in the history
…ary negation (#2382)
  • Loading branch information
renugasaraswathy committed Aug 24, 2020
1 parent e6be621 commit 32fe2bb
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 1 deletion.
32 changes: 32 additions & 0 deletions packages/eslint-plugin/src/rules/no-unnecessary-condition.ts
Expand Up @@ -166,6 +166,14 @@ export default createRule<Options, MessageId>({
* if the type of the node is always true or always false, it's not necessary.
*/
function checkNode(node: TSESTree.Expression): void {
// Check if the node is Unary Negation expression and handle it
if (
node.type === AST_NODE_TYPES.UnaryExpression &&
node.operator === '!'
) {
return checkIfUnaryNegationExpressionIsNecessaryConditional(node);
}

// Since typescript array index signature types don't represent the
// possibility of out-of-bounds access, if we're indexing into an array
// just skip the check, to avoid false positives
Expand Down Expand Up @@ -213,6 +221,30 @@ export default createRule<Options, MessageId>({
}
}

/**
* If it is Unary Negation Expression, check the argument for alwaysTruthy / alwaysFalsy
*/
function checkIfUnaryNegationExpressionIsNecessaryConditional(
node: TSESTree.UnaryExpression,
): void {
if (isArrayIndexExpression(node.argument)) {
return;
}
const type = getNodeType(node.argument);
const messageId = isTypeFlagSet(type, ts.TypeFlags.Never)
? 'never'
: isPossiblyTruthy(type)
? 'alwaysFalsy'
: isPossiblyFalsy(type)
? 'alwaysTruthy'
: undefined;

if (messageId) {
context.report({ node, messageId });
}
return;
}

function checkNodeForNullish(node: TSESTree.Expression): void {
// Since typescript array index signature types don't represent the
// possibility of out-of-bounds access, if we're indexing into an array
Expand Down
Expand Up @@ -445,7 +445,26 @@ declare const key: Key;
foo?.[key]?.trim();
`,
// https://github.com/typescript-eslint/typescript-eslint/issues/2384
`
let latencies: number[][] = [];
function recordData(): void {
if (!latencies[0]) latencies[0] = [];
latencies[0].push(4);
}
recordData();
`,
`
let latencies: number[][] = [];
function recordData(): void {
if (latencies[0]) latencies[0] = [];
latencies[0].push(4);
}
recordData();
`,
`
function test(testVal?: boolean) {
if (testVal ?? true) {
Expand All @@ -458,6 +477,34 @@ function test(testVal?: boolean) {
// Ensure that it's checking in all the right places
{
code: `
const a = null;
if (!a) {
}
`,
errors: [ruleError(3, 5, 'alwaysTruthy')],
},
{
code: `
const a = true;
if (!a) {
}
`,
errors: [ruleError(3, 5, 'alwaysFalsy')],
},
{
code: `
function sayHi(): void {
console.log('Hi!');
}
let speech: never = sayHi();
if (!speech) {
}
`,
errors: [ruleError(7, 5, 'never')],
},
{
code: `
const b1 = true;
declare const b2: boolean;
const t1 = b1 && b2;
Expand Down

0 comments on commit 32fe2bb

Please sign in to comment.