@@ -1258,6 +1258,7 @@ export const enum CheckMode {
1258
1258
RestBindingElement = 1 << 6, // Checking a type that is going to be used to determine the type of a rest binding element
1259
1259
// e.g. in `const { a, ...rest } = foo`, when checking the type of `foo` to determine the type of `rest`,
1260
1260
// we need to preserve generic types instead of substituting them for constraints
1261
+ TypeOnly = 1 << 7, // Called from getTypeOfExpression, diagnostics may be omitted
1261
1262
}
1262
1263
1263
1264
/** @internal */
@@ -36760,7 +36761,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
36760
36761
const rightType = getLastResult(state);
36761
36762
Debug.assertIsDefined(rightType);
36762
36763
36763
- result = checkBinaryLikeExpressionWorker(node.left, node.operatorToken, node.right, leftType, rightType, node);
36764
+ result = checkBinaryLikeExpressionWorker(node.left, node.operatorToken, node.right, leftType, rightType, state.checkMode, node);
36764
36765
}
36765
36766
36766
36767
state.skip = false;
@@ -36831,7 +36832,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
36831
36832
}
36832
36833
36833
36834
const rightType = checkExpression(right, checkMode);
36834
- return checkBinaryLikeExpressionWorker(left, operatorToken, right, leftType, rightType, errorNode);
36835
+ return checkBinaryLikeExpressionWorker(left, operatorToken, right, leftType, rightType, checkMode, errorNode);
36835
36836
}
36836
36837
36837
36838
function checkBinaryLikeExpressionWorker(
@@ -36840,6 +36841,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
36840
36841
right: Expression,
36841
36842
leftType: Type,
36842
36843
rightType: Type,
36844
+ checkMode?: CheckMode,
36843
36845
errorNode?: Node
36844
36846
): Type {
36845
36847
const operator = operatorToken.kind;
@@ -36993,14 +36995,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
36993
36995
case SyntaxKind.ExclamationEqualsToken:
36994
36996
case SyntaxKind.EqualsEqualsEqualsToken:
36995
36997
case SyntaxKind.ExclamationEqualsEqualsToken:
36996
- if (isLiteralExpressionOfObject(left) || isLiteralExpressionOfObject(right)) {
36997
- const eqType = operator === SyntaxKind.EqualsEqualsToken || operator === SyntaxKind.EqualsEqualsEqualsToken;
36998
- error(errorNode, Diagnostics.This_condition_will_always_return_0_since_JavaScript_compares_objects_by_reference_not_value, eqType ? "false" : "true");
36998
+ // We suppress errors in CheckMode.TypeOnly (meaning the invocation came from getTypeOfExpression). During
36999
+ // control flow analysis it is possible for operands to temporarily have narrower types, and those narrower
37000
+ // types may cause the operands to not be comparable. We don't want such errors reported (see #46475).
37001
+ if (!(checkMode && checkMode & CheckMode.TypeOnly)) {
37002
+ if (isLiteralExpressionOfObject(left) || isLiteralExpressionOfObject(right)) {
37003
+ const eqType = operator === SyntaxKind.EqualsEqualsToken || operator === SyntaxKind.EqualsEqualsEqualsToken;
37004
+ error(errorNode, Diagnostics.This_condition_will_always_return_0_since_JavaScript_compares_objects_by_reference_not_value, eqType ? "false" : "true");
37005
+ }
37006
+ checkNaNEquality(errorNode, operator, left, right);
37007
+ reportOperatorErrorUnless((left, right) => isTypeEqualityComparableTo(left, right) || isTypeEqualityComparableTo(right, left));
36999
37008
}
37000
- checkNaNEquality(errorNode, operator, left, right);
37001
- reportOperatorErrorUnless((left, right) => isTypeEqualityComparableTo(left, right) || isTypeEqualityComparableTo(right, left));
37002
37009
return booleanType;
37003
-
37004
37010
case SyntaxKind.InstanceOfKeyword:
37005
37011
return checkInstanceOfExpression(left, right, leftType, rightType);
37006
37012
case SyntaxKind.InKeyword:
@@ -37355,7 +37361,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
37355
37361
}
37356
37362
37357
37363
function checkConditionalExpression(node: ConditionalExpression, checkMode?: CheckMode): Type {
37358
- const type = checkTruthinessExpression(node.condition);
37364
+ const type = checkTruthinessExpression(node.condition, checkMode );
37359
37365
checkTestingKnownTruthyCallableOrAwaitableType(node.condition, type, node.whenTrue);
37360
37366
const type1 = checkExpression(node.whenTrue, checkMode);
37361
37367
const type2 = checkExpression(node.whenFalse, checkMode);
@@ -37736,7 +37742,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
37736
37742
}
37737
37743
}
37738
37744
const startInvocationCount = flowInvocationCount;
37739
- const type = checkExpression(node);
37745
+ const type = checkExpression(node, CheckMode.TypeOnly );
37740
37746
// If control flow analysis was required to determine the type, it is worth caching.
37741
37747
if (flowInvocationCount !== startInvocationCount) {
37742
37748
const cache = flowTypeCache || (flowTypeCache = []);
0 commit comments