Skip to content

Commit b36e5de

Browse files
author
Andy Hanson
committed
Improve error message for == of two different types
1 parent 67d8263 commit b36e5de

8 files changed

+209
-166
lines changed

src/compiler/checker.ts

Lines changed: 46 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21955,7 +21955,20 @@ namespace ts {
2195521955
const leftStr = typeToString(leftType);
2195621956
const rightStr = typeToString(rightType);
2195721957
const errNode = errorNode || operatorToken;
21958-
if (!tryGiveBetterPrimaryError(errNode, leftStr, rightStr)) {
21958+
const equalsInfo = getEqualsInfo(operatorToken.kind);
21959+
if (equalsInfo !== undefined) {
21960+
const explicitConversion = getExplicitConversion(leftType, rightType);
21961+
if (explicitConversion) {
21962+
const diag = explicitConversion.side === "left"
21963+
? Diagnostics.Types_0_and_1_have_no_overlap_Consider_explicitly_converting_the_left_side_using_2_x
21964+
: Diagnostics.Types_0_and_1_have_no_overlap_Consider_explicitly_converting_the_right_side_using_2_x;
21965+
error(errNode, diag, leftStr, rightStr, explicitConversion.conversionFunctionName);
21966+
}
21967+
else {
21968+
error(errNode, Diagnostics.This_condition_will_always_return_0_since_the_types_1_and_2_have_no_overlap, String(!equalsInfo), leftStr, rightStr);
21969+
}
21970+
}
21971+
else {
2195921972
error(
2196021973
errNode,
2196121974
Diagnostics.Operator_0_cannot_be_applied_to_types_1_and_2,
@@ -21965,20 +21978,42 @@ namespace ts {
2196521978
);
2196621979
}
2196721980
}
21981+
}
2196821982

21969-
function tryGiveBetterPrimaryError(errNode: Node, leftStr: string, rightStr: string) {
21970-
switch (operatorToken.kind) {
21971-
case SyntaxKind.EqualsEqualsEqualsToken:
21972-
case SyntaxKind.EqualsEqualsToken:
21973-
return error(errNode, Diagnostics.This_condition_will_always_return_0_since_the_types_1_and_2_have_no_overlap, "false", leftStr, rightStr);
21974-
case SyntaxKind.ExclamationEqualsEqualsToken:
21975-
case SyntaxKind.ExclamationEqualsToken:
21976-
return error(errNode, Diagnostics.This_condition_will_always_return_0_since_the_types_1_and_2_have_no_overlap, "true", leftStr, rightStr);
21977-
}
21978-
return undefined;
21983+
function getEqualsInfo(operatorToken: SyntaxKind): boolean | undefined {
21984+
switch (operatorToken) {
21985+
case SyntaxKind.EqualsEqualsEqualsToken:
21986+
case SyntaxKind.EqualsEqualsToken:
21987+
return true;
21988+
case SyntaxKind.ExclamationEqualsEqualsToken:
21989+
case SyntaxKind.ExclamationEqualsToken:
21990+
return false;
21991+
default:
21992+
return undefined;
2197921993
}
2198021994
}
2198121995

21996+
interface ExplicitConversion {
21997+
readonly side: "left" | "right";
21998+
readonly conversionFunctionName: string;
21999+
}
22000+
function getExplicitConversion(left: Type, right: Type): ExplicitConversion | undefined {
22001+
const convertLeft = getFunctionNameToConvertToType(right);
22002+
if (convertLeft) return { side: "left", conversionFunctionName: convertLeft };
22003+
const convertRight = getFunctionNameToConvertToType(left);
22004+
if (convertRight) return { side: "right", conversionFunctionName: convertRight };
22005+
return undefined;
22006+
}
22007+
function getFunctionNameToConvertToType(type: Type): string | undefined {
22008+
return type.flags & TypeFlags.String
22009+
? "String"
22010+
: type.flags & TypeFlags.Number
22011+
? "Number"
22012+
: type.flags & TypeFlags.Boolean
22013+
? "Boolean"
22014+
: undefined;
22015+
}
22016+
2198222017
function isYieldExpressionInClass(node: YieldExpression): boolean {
2198322018
let current: Node = node;
2198422019
let parent = node.parent;

src/compiler/diagnosticMessages.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2116,6 +2116,14 @@
21162116
"category": "Error",
21172117
"code": 2586
21182118
},
2119+
"Types '{0}' and '{1}' have no overlap. Consider explicitly converting the left side using `{2}(x)`.": {
2120+
"category": "Error",
2121+
"code": 2587
2122+
},
2123+
"Types '{0}' and '{1}' have no overlap. Consider explicitly converting the right side using `{2}(x)`.": {
2124+
"category": "Error",
2125+
"code": 2588
2126+
},
21192127
"JSX element attributes type '{0}' may not be a union type.": {
21202128
"category": "Error",
21212129
"code": 2600

src/testRunner/unittests/tsserverProjectSystem.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5399,7 +5399,7 @@ namespace ts.projectSystem {
53995399
);
54005400
const errorResult = <protocol.Diagnostic[]>session.executeCommand(getErrRequest).response;
54015401
assert.isTrue(errorResult.length === 1);
5402-
assert.equal(errorResult[0].code, Diagnostics.This_condition_will_always_return_0_since_the_types_1_and_2_have_no_overlap.code);
5402+
assert.equal(errorResult[0].code, Diagnostics.Types_0_and_1_have_no_overlap_Consider_explicitly_converting_the_left_side_using_2_x.code);
54035403
});
54045404

54055405
it("should report semantic errors for configured js project with '// @ts-check' and skipLibCheck=true", () => {
@@ -5426,7 +5426,7 @@ namespace ts.projectSystem {
54265426
);
54275427
const errorResult = <protocol.Diagnostic[]>session.executeCommand(getErrRequest).response;
54285428
assert.isTrue(errorResult.length === 1);
5429-
assert.equal(errorResult[0].code, Diagnostics.This_condition_will_always_return_0_since_the_types_1_and_2_have_no_overlap.code);
5429+
assert.equal(errorResult[0].code, Diagnostics.Types_0_and_1_have_no_overlap_Consider_explicitly_converting_the_left_side_using_2_x.code);
54305430
});
54315431

54325432
it("should report semantic errors for configured js project with checkJs=true and skipLibCheck=true", () => {
@@ -5455,7 +5455,7 @@ namespace ts.projectSystem {
54555455
);
54565456
const errorResult = <protocol.Diagnostic[]>session.executeCommand(getErrRequest).response;
54575457
assert.isTrue(errorResult.length === 1);
5458-
assert.equal(errorResult[0].code, Diagnostics.This_condition_will_always_return_0_since_the_types_1_and_2_have_no_overlap.code);
5458+
assert.equal(errorResult[0].code, Diagnostics.Types_0_and_1_have_no_overlap_Consider_explicitly_converting_the_left_side_using_2_x.code);
54595459
});
54605460
});
54615461

0 commit comments

Comments
 (0)