@@ -21955,7 +21955,20 @@ namespace ts {
21955
21955
const leftStr = typeToString(leftType);
21956
21956
const rightStr = typeToString(rightType);
21957
21957
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 {
21959
21972
error(
21960
21973
errNode,
21961
21974
Diagnostics.Operator_0_cannot_be_applied_to_types_1_and_2,
@@ -21965,20 +21978,42 @@ namespace ts {
21965
21978
);
21966
21979
}
21967
21980
}
21981
+ }
21968
21982
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;
21979
21993
}
21980
21994
}
21981
21995
21996
+ interface ExplicitConversion {
21997
+ readonly side: "left" | "right";
21998
+ readonly conversionFunctionName: string;
21999
+ }
22000
+ function getExplicitConversion(left: Type, right: Type): ExplicitConversion | undefined {
22001
+ const convertToRight = getFunctionNameToConvertToType(right);
22002
+ if (convertToRight) return { side: "left", conversionFunctionName: convertToRight };
22003
+ const convertToLeft = getFunctionNameToConvertToType(left);
22004
+ if (convertToLeft) return { side: "right", conversionFunctionName: convertToLeft };
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
+
21982
22017
function isYieldExpressionInClass(node: YieldExpression): boolean {
21983
22018
let current: Node = node;
21984
22019
let parent = node.parent;
0 commit comments