diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 6e7c99a04de19..8e47a5ea3fbc4 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -34621,15 +34621,17 @@ namespace ts { } function checkNaNEquality(errorNode: Node | undefined, operator: SyntaxKind, left: Expression, right: Expression, leftType: Type, rightType: Type) { - const isLeftNaN = leftType.flags & TypeFlags.Number && isNaN(skipParentheses(left)); - const isRightNaN = rightType.flags & TypeFlags.Number && isNaN(skipParentheses(right)); + const isLeftNaN = (leftType.flags & TypeFlags.Number) && isNaN(skipParentheses(left)); + const isRightNaN = (rightType.flags & TypeFlags.Number) && isNaN(skipParentheses(right)); if (isLeftNaN || isRightNaN) { const err = error(errorNode, Diagnostics.This_condition_will_always_return_0, tokenToString(operator === SyntaxKind.EqualsEqualsEqualsToken || operator === SyntaxKind.EqualsEqualsToken ? SyntaxKind.FalseKeyword : SyntaxKind.TrueKeyword)); if (isLeftNaN && isRightNaN) return; + const operatorString = operator === SyntaxKind.ExclamationEqualsEqualsToken || operator === SyntaxKind.ExclamationEqualsToken ? tokenToString(SyntaxKind.ExclamationToken) : ""; const location = isLeftNaN ? right : left; + const expression = skipParentheses(location); addRelatedInfo(err, createDiagnosticForNode(location, Diagnostics.Did_you_mean_0, - `${operator === SyntaxKind.ExclamationEqualsEqualsToken || operator === SyntaxKind.ExclamationEqualsToken ? tokenToString(SyntaxKind.ExclamationToken) : ""}Number.isNaN(${getTextOfNode(location)})`)); + `${operatorString}Number.isNaN(${isEntityNameExpression(expression) ? entityNameToString(expression) : "..."})`)); } } diff --git a/tests/baselines/reference/nanEquality.errors.txt b/tests/baselines/reference/nanEquality.errors.txt index 2c4b78ee66de0..8a47a5be1bd14 100644 --- a/tests/baselines/reference/nanEquality.errors.txt +++ b/tests/baselines/reference/nanEquality.errors.txt @@ -1,3 +1,4 @@ +tests/cases/compiler/nanEquality.ts(1,15): error TS2451: Cannot redeclare block-scoped variable 'x'. tests/cases/compiler/nanEquality.ts(3,5): error TS2845: This condition will always return 'false'. tests/cases/compiler/nanEquality.ts(4,5): error TS2845: This condition will always return 'false'. tests/cases/compiler/nanEquality.ts(6,5): error TS2845: This condition will always return 'false'. @@ -14,10 +15,14 @@ tests/cases/compiler/nanEquality.ts(21,5): error TS2845: This condition will alw tests/cases/compiler/nanEquality.ts(22,5): error TS2845: This condition will always return 'true'. tests/cases/compiler/nanEquality.ts(24,5): error TS2845: This condition will always return 'false'. tests/cases/compiler/nanEquality.ts(25,5): error TS2845: This condition will always return 'true'. +tests/cases/compiler/nanEquality.ts(28,13): error TS2451: Cannot redeclare block-scoped variable 'x'. +tests/cases/compiler/nanEquality.ts(29,5): error TS2845: This condition will always return 'false'. -==== tests/cases/compiler/nanEquality.ts (16 errors) ==== +==== tests/cases/compiler/nanEquality.ts (19 errors) ==== declare const x: number; + ~ +!!! error TS2451: Cannot redeclare block-scoped variable 'x'. if (x === NaN) {} ~~~~~~~~~ @@ -86,4 +91,13 @@ tests/cases/compiler/nanEquality.ts(25,5): error TS2845: This condition will alw if (NaN != NaN) {} ~~~~~~~~~~ !!! error TS2845: This condition will always return 'true'. + + // ... + declare let x: any; + ~ +!!! error TS2451: Cannot redeclare block-scoped variable 'x'. + if (NaN === x[0][1]) {} + ~~~~~~~~~~~~~~~ +!!! error TS2845: This condition will always return 'false'. +!!! related TS1369 tests/cases/compiler/nanEquality.ts:29:13: Did you mean 'Number.isNaN(...)'? \ No newline at end of file diff --git a/tests/baselines/reference/nanEquality.js b/tests/baselines/reference/nanEquality.js index fd6ebcb39eb0f..25998a55a3c97 100644 --- a/tests/baselines/reference/nanEquality.js +++ b/tests/baselines/reference/nanEquality.js @@ -24,6 +24,10 @@ if (NaN !== NaN) {} if (NaN == NaN) {} if (NaN != NaN) {} + +// ... +declare let x: any; +if (NaN === x[0][1]) {} //// [nanEquality.js] @@ -43,3 +47,4 @@ if (NaN === NaN) { } if (NaN !== NaN) { } if (NaN == NaN) { } if (NaN != NaN) { } +if (NaN === x[0][1]) { } diff --git a/tests/baselines/reference/nanEquality.symbols b/tests/baselines/reference/nanEquality.symbols index e15fbcd7f3cfb..d5fe39946e14a 100644 --- a/tests/baselines/reference/nanEquality.symbols +++ b/tests/baselines/reference/nanEquality.symbols @@ -66,3 +66,11 @@ if (NaN != NaN) {} >NaN : Symbol(NaN, Decl(lib.es5.d.ts, --, --)) >NaN : Symbol(NaN, Decl(lib.es5.d.ts, --, --)) +// ... +declare let x: any; +>x : Symbol(x, Decl(nanEquality.ts, 27, 11)) + +if (NaN === x[0][1]) {} +>NaN : Symbol(NaN, Decl(lib.es5.d.ts, --, --)) +>x : Symbol(x, Decl(nanEquality.ts, 0, 13)) + diff --git a/tests/baselines/reference/nanEquality.types b/tests/baselines/reference/nanEquality.types index dc648ec437c65..e255f3e4144cb 100644 --- a/tests/baselines/reference/nanEquality.types +++ b/tests/baselines/reference/nanEquality.types @@ -90,3 +90,16 @@ if (NaN != NaN) {} >NaN : number >NaN : number +// ... +declare let x: any; +>x : any + +if (NaN === x[0][1]) {} +>NaN === x[0][1] : boolean +>NaN : number +>x[0][1] : any +>x[0] : any +>x : number +>0 : 0 +>1 : 1 + diff --git a/tests/cases/compiler/nanEquality.ts b/tests/cases/compiler/nanEquality.ts index d8f66d61d9dda..23eff2ac4e057 100644 --- a/tests/cases/compiler/nanEquality.ts +++ b/tests/cases/compiler/nanEquality.ts @@ -23,3 +23,7 @@ if (NaN !== NaN) {} if (NaN == NaN) {} if (NaN != NaN) {} + +// ... +declare let x: any; +if (NaN === x[0][1]) {} diff --git a/tests/cases/fourslash/fixNaNEquality1.ts b/tests/cases/fourslash/fixNaNEquality1.ts index 1177793c9d307..52004b122fa2d 100644 --- a/tests/cases/fourslash/fixNaNEquality1.ts +++ b/tests/cases/fourslash/fixNaNEquality1.ts @@ -1,9 +1,10 @@ /// -////if (x === NaN) {} +////declare const x: number; +////[|if (x === NaN) {}|] verify.codeFix({ index: 0, description: "Use `Number.isNaN(x)`.", - newFileContent: "if (Number.isNaN(x)) {}", + newRangeContent: "if (Number.isNaN(x)) {}", }); diff --git a/tests/cases/fourslash/fixNaNEquality2.ts b/tests/cases/fourslash/fixNaNEquality2.ts index d93ada01867b3..e941ac7bd4f61 100644 --- a/tests/cases/fourslash/fixNaNEquality2.ts +++ b/tests/cases/fourslash/fixNaNEquality2.ts @@ -1,9 +1,10 @@ /// -////if (NaN === x) {} +////declare const x: number; +////[|if (NaN === x) {}|] verify.codeFix({ index: 0, description: "Use `Number.isNaN(x)`.", - newFileContent: "if (Number.isNaN(x)) {}", + newRangeContent: "if (Number.isNaN(x)) {}", }); diff --git a/tests/cases/fourslash/fixNaNEquality3.ts b/tests/cases/fourslash/fixNaNEquality3.ts index 434408b55dae6..6ae682a83c9a5 100644 --- a/tests/cases/fourslash/fixNaNEquality3.ts +++ b/tests/cases/fourslash/fixNaNEquality3.ts @@ -1,9 +1,10 @@ /// -////if (x !== NaN) {} +////declare const x: number; +////[|if (x !== NaN) {}|] verify.codeFix({ index: 0, description: "Use `!Number.isNaN(x)`.", - newFileContent: "if (!Number.isNaN(x)) {}", + newRangeContent: "if (!Number.isNaN(x)) {}", }); diff --git a/tests/cases/fourslash/fixNaNEquality4.ts b/tests/cases/fourslash/fixNaNEquality4.ts index 689305dbf640b..6f4128317b977 100644 --- a/tests/cases/fourslash/fixNaNEquality4.ts +++ b/tests/cases/fourslash/fixNaNEquality4.ts @@ -1,9 +1,10 @@ /// -////if (NaN !== x) {} +////declare const x: number; +////[|if (NaN !== x) {}|] verify.codeFix({ index: 0, description: "Use `!Number.isNaN(x)`.", - newFileContent: "if (!Number.isNaN(x)) {}", + newRangeContent: "if (!Number.isNaN(x)) {}", }); diff --git a/tests/cases/fourslash/fixNaNEquality5.ts b/tests/cases/fourslash/fixNaNEquality5.ts new file mode 100644 index 0000000000000..00b954f33bd59 --- /dev/null +++ b/tests/cases/fourslash/fixNaNEquality5.ts @@ -0,0 +1,10 @@ +/// + +////declare const x: any; +////[|if (NaN !== x[0][1]) {}|] + +verify.codeFix({ + index: 0, + description: "Use `!Number.isNaN(...)`.", + newRangeContent: "if (!Number.isNaN(x[0][1])) {}", +}); diff --git a/tests/cases/fourslash/fixNaNEquality_all.ts b/tests/cases/fourslash/fixNaNEquality_all.ts index c49a3ce20ebca..e5536ec8f041b 100644 --- a/tests/cases/fourslash/fixNaNEquality_all.ts +++ b/tests/cases/fourslash/fixNaNEquality_all.ts @@ -1,16 +1,22 @@ /// +////declare const x: number; +////declare const y: any; ////if (x === NaN) {} ////if (NaN === x) {} ////if (x !== NaN) {} ////if (NaN !== x) {} +////if (NaN === y[0][1]) {} verify.codeFixAll({ fixId: "fixNaNEquality", fixAllDescription: ts.Diagnostics.Use_Number_isNaN_in_all_conditions.message, newFileContent: -`if (Number.isNaN(x)) {} +`declare const x: number; +declare const y: any; if (Number.isNaN(x)) {} +if (Number.isNaN(x)) {} +if (!Number.isNaN(x)) {} if (!Number.isNaN(x)) {} -if (!Number.isNaN(x)) {}` +if (Number.isNaN(y[0][1])) {}` });