diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts
index a457944e027a7..ff65a45c176cb 100644
--- a/src/compiler/checker.ts
+++ b/src/compiler/checker.ts
@@ -34386,6 +34386,7 @@ namespace ts {
const eqType = operator === SyntaxKind.EqualsEqualsToken || operator === SyntaxKind.EqualsEqualsEqualsToken;
error(errorNode, Diagnostics.This_condition_will_always_return_0_since_JavaScript_compares_objects_by_reference_not_value, eqType ? "false" : "true");
}
+ checkNaNEquality(errorNode, operator, left, right);
reportOperatorErrorUnless((left, right) => isTypeEqualityComparableTo(left, right) || isTypeEqualityComparableTo(right, left));
return booleanType;
@@ -34618,6 +34619,23 @@ namespace ts {
return undefined;
}
}
+
+ function checkNaNEquality(errorNode: Node | undefined, operator: SyntaxKind, left: Expression, right: Expression) {
+ const isLeftNaN = isNaN(left);
+ const isRightNaN = isNaN(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 location = isLeftNaN ? right : left;
+ addRelatedInfo(err, createDiagnosticForNode(location, Diagnostics.Did_you_mean_0,
+ `${operator === SyntaxKind.ExclamationEqualsEqualsToken || operator === SyntaxKind.ExclamationEqualsToken ? tokenToString(SyntaxKind.ExclamationToken) : ""}Number.isNaN(${getTextOfNode(location)})`));
+ }
+ }
+
+ function isNaN(expr: Expression): boolean {
+ return isIdentifier(expr) ? expr.escapedText === "NaN" : isNaN(skipParentheses(expr));
+ }
}
function getBaseTypesIfUnrelated(leftType: Type, rightType: Type, isRelated: (left: Type, right: Type) => boolean): [Type, Type] {
diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json
index 6cec02b9e1a41..c4cf974c0d59b 100644
--- a/src/compiler/diagnosticMessages.json
+++ b/src/compiler/diagnosticMessages.json
@@ -3559,6 +3559,10 @@
"category": "Error",
"code": 2844
},
+ "This condition will always return '{0}'.": {
+ "category": "Error",
+ "code": 2845
+ },
"Import declaration '{0}' is using private name '{1}'.": {
"category": "Error",
@@ -7352,7 +7356,14 @@
"category": "Message",
"code": 95173
},
-
+ "Use `{0}`.": {
+ "category": "Message",
+ "code": 95174
+ },
+ "Use `Number.isNaN` in all conditions.": {
+ "category": "Message",
+ "code": 95175
+ },
"No value exists in scope for the shorthand property '{0}'. Either declare one or provide an initializer.": {
"category": "Error",
diff --git a/src/services/codefixes/fixAddMissingConstraint.ts b/src/services/codefixes/fixAddMissingConstraint.ts
index 2d3b6c51a346c..c8cbce9ee02af 100644
--- a/src/services/codefixes/fixAddMissingConstraint.ts
+++ b/src/services/codefixes/fixAddMissingConstraint.ts
@@ -94,15 +94,6 @@ namespace ts.codefix {
}
}
- function findAncestorMatchingSpan(sourceFile: SourceFile, span: TextSpan): Node {
- const end = textSpanEnd(span);
- let token = getTokenAtPosition(sourceFile, span.start);
- while (token.end < end) {
- token = token.parent;
- }
- return token;
- }
-
function tryGetConstraintFromDiagnosticMessage(messageText: string | DiagnosticMessageChain) {
const [_, constraint] = flattenDiagnosticMessageText(messageText, "\n", 0).match(/`extends (.*)`/) || [];
return constraint;
diff --git a/src/services/codefixes/fixNaNEquality.ts b/src/services/codefixes/fixNaNEquality.ts
new file mode 100644
index 0000000000000..7448aa52be725
--- /dev/null
+++ b/src/services/codefixes/fixNaNEquality.ts
@@ -0,0 +1,65 @@
+/* @internal */
+namespace ts.codefix {
+ const fixId = "fixNaNEquality";
+ const errorCodes = [
+ Diagnostics.This_condition_will_always_return_0.code,
+ ];
+
+ registerCodeFix({
+ errorCodes,
+ getCodeActions(context) {
+ const { sourceFile, span, program } = context;
+ const info = getInfo(program, sourceFile, span);
+ if (info === undefined) return;
+
+ const { suggestion, expression, arg } = info;
+ const changes = textChanges.ChangeTracker.with(context, t => doChange(t, sourceFile, arg, expression));
+ return [createCodeFixAction(fixId, changes, [Diagnostics.Use_0, suggestion], fixId, Diagnostics.Use_Number_isNaN_in_all_conditions)];
+ },
+ fixIds: [fixId],
+ getAllCodeActions: context => {
+ return codeFixAll(context, errorCodes, (changes, diag) => {
+ const info = getInfo(context.program, diag.file, createTextSpan(diag.start, diag.length));
+ if (info) {
+ doChange(changes, diag.file, info.arg, info.expression);
+ }
+ });
+ }
+ });
+
+ interface Info {
+ suggestion: string;
+ expression: BinaryExpression;
+ arg: Expression;
+ }
+
+ function getInfo(program: Program, sourceFile: SourceFile, span: TextSpan): Info | undefined {
+ const diag = find(program.getSemanticDiagnostics(sourceFile), diag => diag.start === span.start && diag.length === span.length);
+ if (diag === undefined || diag.relatedInformation === undefined) return;
+
+ const related = find(diag.relatedInformation, related => related.code === Diagnostics.Did_you_mean_0.code);
+ if (related === undefined || related.file === undefined || related.start === undefined || related.length === undefined) return;
+
+ const token = findAncestorMatchingSpan(related.file, createTextSpan(related.start, related.length));
+ if (token === undefined) return;
+
+ if (isExpression(token) && isBinaryExpression(token.parent)) {
+ return { suggestion: getSuggestion(related.messageText), expression: token.parent, arg: token };
+ }
+ return undefined;
+ }
+
+ function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, arg: Expression, expression: BinaryExpression) {
+ const callExpression = factory.createCallExpression(
+ factory.createPropertyAccessExpression(factory.createIdentifier("Number"), factory.createIdentifier("isNaN")), /*typeArguments*/ undefined, [arg]);
+ const operator = expression.operatorToken.kind ;
+ changes.replaceNode(sourceFile, expression,
+ operator === SyntaxKind.ExclamationEqualsEqualsToken || operator === SyntaxKind.ExclamationEqualsToken
+ ? factory.createPrefixUnaryExpression(SyntaxKind.ExclamationToken, callExpression) : callExpression);
+ }
+
+ function getSuggestion(messageText: string | DiagnosticMessageChain) {
+ const [_, suggestion] = flattenDiagnosticMessageText(messageText, "\n", 0).match(/\'(.*)\'/) || [];
+ return suggestion;
+ }
+}
diff --git a/src/services/codefixes/helpers.ts b/src/services/codefixes/helpers.ts
index ba8bd0453dd09..9d578b5b0da1c 100644
--- a/src/services/codefixes/helpers.ts
+++ b/src/services/codefixes/helpers.ts
@@ -743,4 +743,13 @@ namespace ts.codefix {
export function importSymbols(importAdder: ImportAdder, symbols: readonly Symbol[]) {
symbols.forEach(s => importAdder.addImportFromExportedSymbol(s, /*isValidTypeOnlyUseSite*/ true));
}
+
+ export function findAncestorMatchingSpan(sourceFile: SourceFile, span: TextSpan): Node {
+ const end = textSpanEnd(span);
+ let token = getTokenAtPosition(sourceFile, span.start);
+ while (token.end < end) {
+ token = token.parent;
+ }
+ return token;
+ }
}
diff --git a/src/services/tsconfig.json b/src/services/tsconfig.json
index 949d5c8a964a7..2237163ebb20d 100644
--- a/src/services/tsconfig.json
+++ b/src/services/tsconfig.json
@@ -82,6 +82,7 @@
"codefixes/fixConstructorForDerivedNeedSuperCall.ts",
"codefixes/fixEnableExperimentalDecorators.ts",
"codefixes/fixEnableJsxFlag.ts",
+ "codefixes/fixNaNEquality.ts",
"codefixes/fixModuleAndTargetOptions.ts",
"codefixes/fixPropertyAssignment.ts",
"codefixes/fixExtendsInterfaceBecomesImplements.ts",
diff --git a/tests/baselines/reference/nanEquality.errors.txt b/tests/baselines/reference/nanEquality.errors.txt
new file mode 100644
index 0000000000000..2c4b78ee66de0
--- /dev/null
+++ b/tests/baselines/reference/nanEquality.errors.txt
@@ -0,0 +1,89 @@
+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'.
+tests/cases/compiler/nanEquality.ts(7,5): error TS2845: This condition will always return 'false'.
+tests/cases/compiler/nanEquality.ts(9,5): error TS2845: This condition will always return 'true'.
+tests/cases/compiler/nanEquality.ts(10,5): error TS2845: This condition will always return 'true'.
+tests/cases/compiler/nanEquality.ts(12,5): error TS2845: This condition will always return 'true'.
+tests/cases/compiler/nanEquality.ts(13,5): error TS2845: This condition will always return 'true'.
+tests/cases/compiler/nanEquality.ts(15,5): error TS2845: This condition will always return 'false'.
+tests/cases/compiler/nanEquality.ts(16,5): error TS2845: This condition will always return 'false'.
+tests/cases/compiler/nanEquality.ts(18,5): error TS2845: This condition will always return 'true'.
+tests/cases/compiler/nanEquality.ts(19,5): error TS2845: This condition will always return 'true'.
+tests/cases/compiler/nanEquality.ts(21,5): error TS2845: This condition will always return 'false'.
+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 (16 errors) ====
+ declare const x: number;
+
+ if (x === NaN) {}
+ ~~~~~~~~~
+!!! error TS2845: This condition will always return 'false'.
+!!! related TS1369 tests/cases/compiler/nanEquality.ts:3:5: Did you mean 'Number.isNaN(x)'?
+ if (NaN === x) {}
+ ~~~~~~~~~
+!!! error TS2845: This condition will always return 'false'.
+!!! related TS1369 tests/cases/compiler/nanEquality.ts:4:13: Did you mean 'Number.isNaN(x)'?
+
+ if (x == NaN) {}
+ ~~~~~~~~
+!!! error TS2845: This condition will always return 'false'.
+!!! related TS1369 tests/cases/compiler/nanEquality.ts:6:5: Did you mean 'Number.isNaN(x)'?
+ if (NaN == x) {}
+ ~~~~~~~~
+!!! error TS2845: This condition will always return 'false'.
+!!! related TS1369 tests/cases/compiler/nanEquality.ts:7:12: Did you mean 'Number.isNaN(x)'?
+
+ if (x !== NaN) {}
+ ~~~~~~~~~
+!!! error TS2845: This condition will always return 'true'.
+!!! related TS1369 tests/cases/compiler/nanEquality.ts:9:5: Did you mean '!Number.isNaN(x)'?
+ if (NaN !== x) {}
+ ~~~~~~~~~
+!!! error TS2845: This condition will always return 'true'.
+!!! related TS1369 tests/cases/compiler/nanEquality.ts:10:13: Did you mean '!Number.isNaN(x)'?
+
+ if (x != NaN) {}
+ ~~~~~~~~
+!!! error TS2845: This condition will always return 'true'.
+!!! related TS1369 tests/cases/compiler/nanEquality.ts:12:5: Did you mean '!Number.isNaN(x)'?
+ if (NaN != x) {}
+ ~~~~~~~~
+!!! error TS2845: This condition will always return 'true'.
+!!! related TS1369 tests/cases/compiler/nanEquality.ts:13:12: Did you mean '!Number.isNaN(x)'?
+
+ if (x === ((NaN))) {}
+ ~~~~~~~~~~~~~
+!!! error TS2845: This condition will always return 'false'.
+!!! related TS1369 tests/cases/compiler/nanEquality.ts:15:5: Did you mean 'Number.isNaN(x)'?
+ if (((NaN)) === x) {}
+ ~~~~~~~~~~~~~
+!!! error TS2845: This condition will always return 'false'.
+!!! related TS1369 tests/cases/compiler/nanEquality.ts:16:17: Did you mean 'Number.isNaN(x)'?
+
+ if (x !== ((NaN))) {}
+ ~~~~~~~~~~~~~
+!!! error TS2845: This condition will always return 'true'.
+!!! related TS1369 tests/cases/compiler/nanEquality.ts:18:5: Did you mean '!Number.isNaN(x)'?
+ if (((NaN)) !== x) {}
+ ~~~~~~~~~~~~~
+!!! error TS2845: This condition will always return 'true'.
+!!! related TS1369 tests/cases/compiler/nanEquality.ts:19:17: Did you mean '!Number.isNaN(x)'?
+
+ if (NaN === NaN) {}
+ ~~~~~~~~~~~
+!!! error TS2845: This condition will always return 'false'.
+ if (NaN !== NaN) {}
+ ~~~~~~~~~~~
+!!! error TS2845: This condition will always return 'true'.
+
+ if (NaN == NaN) {}
+ ~~~~~~~~~~
+!!! error TS2845: This condition will always return 'false'.
+ if (NaN != NaN) {}
+ ~~~~~~~~~~
+!!! error TS2845: This condition will always return 'true'.
+
\ No newline at end of file
diff --git a/tests/baselines/reference/nanEquality.js b/tests/baselines/reference/nanEquality.js
new file mode 100644
index 0000000000000..fd6ebcb39eb0f
--- /dev/null
+++ b/tests/baselines/reference/nanEquality.js
@@ -0,0 +1,45 @@
+//// [nanEquality.ts]
+declare const x: number;
+
+if (x === NaN) {}
+if (NaN === x) {}
+
+if (x == NaN) {}
+if (NaN == x) {}
+
+if (x !== NaN) {}
+if (NaN !== x) {}
+
+if (x != NaN) {}
+if (NaN != x) {}
+
+if (x === ((NaN))) {}
+if (((NaN)) === x) {}
+
+if (x !== ((NaN))) {}
+if (((NaN)) !== x) {}
+
+if (NaN === NaN) {}
+if (NaN !== NaN) {}
+
+if (NaN == NaN) {}
+if (NaN != NaN) {}
+
+
+//// [nanEquality.js]
+if (x === NaN) { }
+if (NaN === x) { }
+if (x == NaN) { }
+if (NaN == x) { }
+if (x !== NaN) { }
+if (NaN !== x) { }
+if (x != NaN) { }
+if (NaN != x) { }
+if (x === ((NaN))) { }
+if (((NaN)) === x) { }
+if (x !== ((NaN))) { }
+if (((NaN)) !== x) { }
+if (NaN === NaN) { }
+if (NaN !== NaN) { }
+if (NaN == NaN) { }
+if (NaN != NaN) { }
diff --git a/tests/baselines/reference/nanEquality.symbols b/tests/baselines/reference/nanEquality.symbols
new file mode 100644
index 0000000000000..e15fbcd7f3cfb
--- /dev/null
+++ b/tests/baselines/reference/nanEquality.symbols
@@ -0,0 +1,68 @@
+=== tests/cases/compiler/nanEquality.ts ===
+declare const x: number;
+>x : Symbol(x, Decl(nanEquality.ts, 0, 13))
+
+if (x === NaN) {}
+>x : Symbol(x, Decl(nanEquality.ts, 0, 13))
+>NaN : Symbol(NaN, Decl(lib.es5.d.ts, --, --))
+
+if (NaN === x) {}
+>NaN : Symbol(NaN, Decl(lib.es5.d.ts, --, --))
+>x : Symbol(x, Decl(nanEquality.ts, 0, 13))
+
+if (x == NaN) {}
+>x : Symbol(x, Decl(nanEquality.ts, 0, 13))
+>NaN : Symbol(NaN, Decl(lib.es5.d.ts, --, --))
+
+if (NaN == x) {}
+>NaN : Symbol(NaN, Decl(lib.es5.d.ts, --, --))
+>x : Symbol(x, Decl(nanEquality.ts, 0, 13))
+
+if (x !== NaN) {}
+>x : Symbol(x, Decl(nanEquality.ts, 0, 13))
+>NaN : Symbol(NaN, Decl(lib.es5.d.ts, --, --))
+
+if (NaN !== x) {}
+>NaN : Symbol(NaN, Decl(lib.es5.d.ts, --, --))
+>x : Symbol(x, Decl(nanEquality.ts, 0, 13))
+
+if (x != NaN) {}
+>x : Symbol(x, Decl(nanEquality.ts, 0, 13))
+>NaN : Symbol(NaN, Decl(lib.es5.d.ts, --, --))
+
+if (NaN != x) {}
+>NaN : Symbol(NaN, Decl(lib.es5.d.ts, --, --))
+>x : Symbol(x, Decl(nanEquality.ts, 0, 13))
+
+if (x === ((NaN))) {}
+>x : Symbol(x, Decl(nanEquality.ts, 0, 13))
+>NaN : Symbol(NaN, Decl(lib.es5.d.ts, --, --))
+
+if (((NaN)) === x) {}
+>NaN : Symbol(NaN, Decl(lib.es5.d.ts, --, --))
+>x : Symbol(x, Decl(nanEquality.ts, 0, 13))
+
+if (x !== ((NaN))) {}
+>x : Symbol(x, Decl(nanEquality.ts, 0, 13))
+>NaN : Symbol(NaN, Decl(lib.es5.d.ts, --, --))
+
+if (((NaN)) !== x) {}
+>NaN : Symbol(NaN, Decl(lib.es5.d.ts, --, --))
+>x : Symbol(x, Decl(nanEquality.ts, 0, 13))
+
+if (NaN === NaN) {}
+>NaN : Symbol(NaN, Decl(lib.es5.d.ts, --, --))
+>NaN : Symbol(NaN, Decl(lib.es5.d.ts, --, --))
+
+if (NaN !== NaN) {}
+>NaN : Symbol(NaN, Decl(lib.es5.d.ts, --, --))
+>NaN : Symbol(NaN, Decl(lib.es5.d.ts, --, --))
+
+if (NaN == NaN) {}
+>NaN : Symbol(NaN, Decl(lib.es5.d.ts, --, --))
+>NaN : Symbol(NaN, Decl(lib.es5.d.ts, --, --))
+
+if (NaN != NaN) {}
+>NaN : Symbol(NaN, Decl(lib.es5.d.ts, --, --))
+>NaN : Symbol(NaN, Decl(lib.es5.d.ts, --, --))
+
diff --git a/tests/baselines/reference/nanEquality.types b/tests/baselines/reference/nanEquality.types
new file mode 100644
index 0000000000000..dc648ec437c65
--- /dev/null
+++ b/tests/baselines/reference/nanEquality.types
@@ -0,0 +1,92 @@
+=== tests/cases/compiler/nanEquality.ts ===
+declare const x: number;
+>x : number
+
+if (x === NaN) {}
+>x === NaN : boolean
+>x : number
+>NaN : number
+
+if (NaN === x) {}
+>NaN === x : boolean
+>NaN : number
+>x : number
+
+if (x == NaN) {}
+>x == NaN : boolean
+>x : number
+>NaN : number
+
+if (NaN == x) {}
+>NaN == x : boolean
+>NaN : number
+>x : number
+
+if (x !== NaN) {}
+>x !== NaN : boolean
+>x : number
+>NaN : number
+
+if (NaN !== x) {}
+>NaN !== x : boolean
+>NaN : number
+>x : number
+
+if (x != NaN) {}
+>x != NaN : boolean
+>x : number
+>NaN : number
+
+if (NaN != x) {}
+>NaN != x : boolean
+>NaN : number
+>x : number
+
+if (x === ((NaN))) {}
+>x === ((NaN)) : boolean
+>x : number
+>((NaN)) : number
+>(NaN) : number
+>NaN : number
+
+if (((NaN)) === x) {}
+>((NaN)) === x : boolean
+>((NaN)) : number
+>(NaN) : number
+>NaN : number
+>x : number
+
+if (x !== ((NaN))) {}
+>x !== ((NaN)) : boolean
+>x : number
+>((NaN)) : number
+>(NaN) : number
+>NaN : number
+
+if (((NaN)) !== x) {}
+>((NaN)) !== x : boolean
+>((NaN)) : number
+>(NaN) : number
+>NaN : number
+>x : number
+
+if (NaN === NaN) {}
+>NaN === NaN : boolean
+>NaN : number
+>NaN : number
+
+if (NaN !== NaN) {}
+>NaN !== NaN : boolean
+>NaN : number
+>NaN : number
+
+if (NaN == NaN) {}
+>NaN == NaN : boolean
+>NaN : number
+>NaN : number
+
+if (NaN != NaN) {}
+>NaN != NaN : boolean
+>NaN : number
+>NaN : number
+
diff --git a/tests/cases/compiler/nanEquality.ts b/tests/cases/compiler/nanEquality.ts
new file mode 100644
index 0000000000000..d8f66d61d9dda
--- /dev/null
+++ b/tests/cases/compiler/nanEquality.ts
@@ -0,0 +1,25 @@
+declare const x: number;
+
+if (x === NaN) {}
+if (NaN === x) {}
+
+if (x == NaN) {}
+if (NaN == x) {}
+
+if (x !== NaN) {}
+if (NaN !== x) {}
+
+if (x != NaN) {}
+if (NaN != x) {}
+
+if (x === ((NaN))) {}
+if (((NaN)) === x) {}
+
+if (x !== ((NaN))) {}
+if (((NaN)) !== x) {}
+
+if (NaN === NaN) {}
+if (NaN !== NaN) {}
+
+if (NaN == NaN) {}
+if (NaN != NaN) {}
diff --git a/tests/cases/fourslash/fixNaNEquality1.ts b/tests/cases/fourslash/fixNaNEquality1.ts
new file mode 100644
index 0000000000000..1177793c9d307
--- /dev/null
+++ b/tests/cases/fourslash/fixNaNEquality1.ts
@@ -0,0 +1,9 @@
+///
+
+////if (x === NaN) {}
+
+verify.codeFix({
+ index: 0,
+ description: "Use `Number.isNaN(x)`.",
+ newFileContent: "if (Number.isNaN(x)) {}",
+});
diff --git a/tests/cases/fourslash/fixNaNEquality2.ts b/tests/cases/fourslash/fixNaNEquality2.ts
new file mode 100644
index 0000000000000..d93ada01867b3
--- /dev/null
+++ b/tests/cases/fourslash/fixNaNEquality2.ts
@@ -0,0 +1,9 @@
+///
+
+////if (NaN === x) {}
+
+verify.codeFix({
+ index: 0,
+ description: "Use `Number.isNaN(x)`.",
+ newFileContent: "if (Number.isNaN(x)) {}",
+});
diff --git a/tests/cases/fourslash/fixNaNEquality3.ts b/tests/cases/fourslash/fixNaNEquality3.ts
new file mode 100644
index 0000000000000..434408b55dae6
--- /dev/null
+++ b/tests/cases/fourslash/fixNaNEquality3.ts
@@ -0,0 +1,9 @@
+///
+
+////if (x !== NaN) {}
+
+verify.codeFix({
+ index: 0,
+ description: "Use `!Number.isNaN(x)`.",
+ newFileContent: "if (!Number.isNaN(x)) {}",
+});
diff --git a/tests/cases/fourslash/fixNaNEquality4.ts b/tests/cases/fourslash/fixNaNEquality4.ts
new file mode 100644
index 0000000000000..689305dbf640b
--- /dev/null
+++ b/tests/cases/fourslash/fixNaNEquality4.ts
@@ -0,0 +1,9 @@
+///
+
+////if (NaN !== x) {}
+
+verify.codeFix({
+ index: 0,
+ description: "Use `!Number.isNaN(x)`.",
+ newFileContent: "if (!Number.isNaN(x)) {}",
+});
diff --git a/tests/cases/fourslash/fixNaNEquality_all.ts b/tests/cases/fourslash/fixNaNEquality_all.ts
new file mode 100644
index 0000000000000..c49a3ce20ebca
--- /dev/null
+++ b/tests/cases/fourslash/fixNaNEquality_all.ts
@@ -0,0 +1,16 @@
+///
+
+////if (x === NaN) {}
+////if (NaN === x) {}
+////if (x !== NaN) {}
+////if (NaN !== x) {}
+
+verify.codeFixAll({
+ fixId: "fixNaNEquality",
+ fixAllDescription: ts.Diagnostics.Use_Number_isNaN_in_all_conditions.message,
+ newFileContent:
+`if (Number.isNaN(x)) {}
+if (Number.isNaN(x)) {}
+if (!Number.isNaN(x)) {}
+if (!Number.isNaN(x)) {}`
+});