Skip to content

Commit 2acbcee

Browse files
authored
Improve comparison operators type checking to disallow unions containing numbers as an operand (#52048)
1 parent e551516 commit 2acbcee

7 files changed

+255
-4
lines changed

Diff for: src/compiler/checker.ts

+9-3
Original file line numberDiff line numberDiff line change
@@ -36336,9 +36336,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3633636336
if (checkForDisallowedESSymbolOperand(operator)) {
3633736337
leftType = getBaseTypeOfLiteralType(checkNonNullType(leftType, left));
3633836338
rightType = getBaseTypeOfLiteralType(checkNonNullType(rightType, right));
36339-
reportOperatorErrorUnless((left, right) =>
36340-
isTypeComparableTo(left, right) || isTypeComparableTo(right, left) || (
36341-
isTypeAssignableTo(left, numberOrBigIntType) && isTypeAssignableTo(right, numberOrBigIntType)));
36339+
reportOperatorErrorUnless((left, right) => {
36340+
if (isTypeAny(left) || isTypeAny(right)) {
36341+
return true;
36342+
}
36343+
const leftAssignableToNumber = isTypeAssignableTo(left, numberOrBigIntType);
36344+
const rightAssignableToNumber = isTypeAssignableTo(right, numberOrBigIntType);
36345+
return leftAssignableToNumber && rightAssignableToNumber ||
36346+
!leftAssignableToNumber && !rightAssignableToNumber && areTypesComparable(left, right);
36347+
});
3634236348
}
3634336349
return booleanType;
3634436350
case SyntaxKind.EqualsEqualsToken:

Diff for: tests/baselines/reference/comparisonOperatorWithNoRelationshipTypeParameter.errors.txt

+97-1
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,41 @@ tests/cases/conformance/expressions/binaryOperators/comparisonOperator/compariso
66
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(17,14): error TS2367: This comparison appears to be unintentional because the types 'T' and 'U' have no overlap.
77
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(18,14): error TS2367: This comparison appears to be unintentional because the types 'T' and 'U' have no overlap.
88
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(19,14): error TS2367: This comparison appears to be unintentional because the types 'T' and 'U' have no overlap.
9+
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(23,16): error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
10+
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(26,16): error TS2365: Operator '<' cannot be applied to types 'T' and 'E'.
11+
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(31,16): error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
12+
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(34,16): error TS2365: Operator '<' cannot be applied to types 'E' and 'T'.
13+
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(40,16): error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
14+
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(43,16): error TS2365: Operator '<' cannot be applied to types 'T' and 'E'.
15+
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(48,16): error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
16+
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(51,16): error TS2365: Operator '<' cannot be applied to types 'E' and 'T'.
17+
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(57,16): error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
18+
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(60,16): error TS2365: Operator '<' cannot be applied to types 'T' and 'E'.
19+
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(65,16): error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
20+
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(68,16): error TS2365: Operator '<' cannot be applied to types 'E' and 'T'.
21+
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(74,16): error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
22+
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(77,16): error TS2365: Operator '<' cannot be applied to types 'T' and 'E'.
23+
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(82,16): error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
24+
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(85,16): error TS2365: Operator '<' cannot be applied to types 'E' and 'T'.
25+
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(91,16): error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
26+
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(94,16): error TS2365: Operator '<' cannot be applied to types 'T' and 'E'.
27+
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(99,16): error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
28+
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(102,16): error TS2365: Operator '<' cannot be applied to types 'E' and 'T'.
29+
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(108,16): error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
30+
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(111,16): error TS2365: Operator '<' cannot be applied to types 'T' and 'E'.
31+
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(116,16): error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
32+
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(119,16): error TS2365: Operator '<' cannot be applied to types 'E' and 'T'.
33+
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(125,16): error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
34+
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(128,16): error TS2365: Operator '<' cannot be applied to types 'T' and 'E'.
35+
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(133,16): error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
36+
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(136,16): error TS2365: Operator '<' cannot be applied to types 'E' and 'T'.
37+
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(142,16): error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
38+
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(145,16): error TS2365: Operator '<' cannot be applied to types 'T' and 'E'.
39+
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(150,16): error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
40+
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(153,16): error TS2365: Operator '<' cannot be applied to types 'E' and 'T'.
941

1042

11-
==== tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts (8 errors) ====
43+
==== tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts (40 errors) ====
1244
enum E { a, b, c }
1345

1446
var a: boolean;
@@ -48,136 +80,200 @@ tests/cases/conformance/expressions/binaryOperators/comparisonOperator/compariso
4880
// operator <
4981
var r1a1 = t < a;
5082
var r1a2 = t < b;
83+
~~~~~
84+
!!! error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
5185
var r1a3 = t < c;
5286
var r1a4 = t < d;
5387
var r1a5 = t < e;
88+
~~~~~
89+
!!! error TS2365: Operator '<' cannot be applied to types 'T' and 'E'.
5490
var r1a6 = t < f;
5591
var r1a7 = t < g;
5692

5793
var r1b1 = a < t;
5894
var r1b2 = b < t;
95+
~~~~~
96+
!!! error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
5997
var r1b3 = c < t;
6098
var r1b4 = d < t;
6199
var r1b5 = e < t;
100+
~~~~~
101+
!!! error TS2365: Operator '<' cannot be applied to types 'E' and 'T'.
62102
var r1b6 = f < t;
63103
var r1b7 = g < t;
64104

65105
// operator >
66106
var r2a1 = t < a;
67107
var r2a2 = t < b;
108+
~~~~~
109+
!!! error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
68110
var r2a3 = t < c;
69111
var r2a4 = t < d;
70112
var r2a5 = t < e;
113+
~~~~~
114+
!!! error TS2365: Operator '<' cannot be applied to types 'T' and 'E'.
71115
var r2a6 = t < f;
72116
var r2a7 = t < g;
73117

74118
var r2b1 = a < t;
75119
var r2b2 = b < t;
120+
~~~~~
121+
!!! error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
76122
var r2b3 = c < t;
77123
var r2b4 = d < t;
78124
var r2b5 = e < t;
125+
~~~~~
126+
!!! error TS2365: Operator '<' cannot be applied to types 'E' and 'T'.
79127
var r2b6 = f < t;
80128
var r2b7 = g < t;
81129

82130
// operator <=
83131
var r3a1 = t < a;
84132
var r3a2 = t < b;
133+
~~~~~
134+
!!! error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
85135
var r3a3 = t < c;
86136
var r3a4 = t < d;
87137
var r3a5 = t < e;
138+
~~~~~
139+
!!! error TS2365: Operator '<' cannot be applied to types 'T' and 'E'.
88140
var r3a6 = t < f;
89141
var r3a7 = t < g;
90142

91143
var r3b1 = a < t;
92144
var r3b2 = b < t;
145+
~~~~~
146+
!!! error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
93147
var r3b3 = c < t;
94148
var r3b4 = d < t;
95149
var r3b5 = e < t;
150+
~~~~~
151+
!!! error TS2365: Operator '<' cannot be applied to types 'E' and 'T'.
96152
var r3b6 = f < t;
97153
var r3b7 = g < t;
98154

99155
// operator >=
100156
var r4a1 = t < a;
101157
var r4a2 = t < b;
158+
~~~~~
159+
!!! error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
102160
var r4a3 = t < c;
103161
var r4a4 = t < d;
104162
var r4a5 = t < e;
163+
~~~~~
164+
!!! error TS2365: Operator '<' cannot be applied to types 'T' and 'E'.
105165
var r4a6 = t < f;
106166
var r4a7 = t < g;
107167

108168
var r4b1 = a < t;
109169
var r4b2 = b < t;
170+
~~~~~
171+
!!! error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
110172
var r4b3 = c < t;
111173
var r4b4 = d < t;
112174
var r4b5 = e < t;
175+
~~~~~
176+
!!! error TS2365: Operator '<' cannot be applied to types 'E' and 'T'.
113177
var r4b6 = f < t;
114178
var r4b7 = g < t;
115179

116180
// operator ==
117181
var r5a1 = t < a;
118182
var r5a2 = t < b;
183+
~~~~~
184+
!!! error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
119185
var r5a3 = t < c;
120186
var r5a4 = t < d;
121187
var r5a5 = t < e;
188+
~~~~~
189+
!!! error TS2365: Operator '<' cannot be applied to types 'T' and 'E'.
122190
var r5a6 = t < f;
123191
var r5a7 = t < g;
124192

125193
var r5b1 = a < t;
126194
var r5b2 = b < t;
195+
~~~~~
196+
!!! error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
127197
var r5b3 = c < t;
128198
var r5b4 = d < t;
129199
var r5b5 = e < t;
200+
~~~~~
201+
!!! error TS2365: Operator '<' cannot be applied to types 'E' and 'T'.
130202
var r5b6 = f < t;
131203
var r5b7 = g < t;
132204

133205
// operator !=
134206
var r6a1 = t < a;
135207
var r6a2 = t < b;
208+
~~~~~
209+
!!! error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
136210
var r6a3 = t < c;
137211
var r6a4 = t < d;
138212
var r6a5 = t < e;
213+
~~~~~
214+
!!! error TS2365: Operator '<' cannot be applied to types 'T' and 'E'.
139215
var r6a6 = t < f;
140216
var r6a7 = t < g;
141217

142218
var r6b1 = a < t;
143219
var r6b2 = b < t;
220+
~~~~~
221+
!!! error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
144222
var r6b3 = c < t;
145223
var r6b4 = d < t;
146224
var r6b5 = e < t;
225+
~~~~~
226+
!!! error TS2365: Operator '<' cannot be applied to types 'E' and 'T'.
147227
var r6b6 = f < t;
148228
var r6b7 = g < t;
149229

150230
// operator ===
151231
var r7a1 = t < a;
152232
var r7a2 = t < b;
233+
~~~~~
234+
!!! error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
153235
var r7a3 = t < c;
154236
var r7a4 = t < d;
155237
var r7a5 = t < e;
238+
~~~~~
239+
!!! error TS2365: Operator '<' cannot be applied to types 'T' and 'E'.
156240
var r7a6 = t < f;
157241
var r7a7 = t < g;
158242

159243
var r7b1 = a < t;
160244
var r7b2 = b < t;
245+
~~~~~
246+
!!! error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
161247
var r7b3 = c < t;
162248
var r7b4 = d < t;
163249
var r7b5 = e < t;
250+
~~~~~
251+
!!! error TS2365: Operator '<' cannot be applied to types 'E' and 'T'.
164252
var r7b6 = f < t;
165253
var r7b7 = g < t;
166254

167255
// operator !==
168256
var r8a1 = t < a;
169257
var r8a2 = t < b;
258+
~~~~~
259+
!!! error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
170260
var r8a3 = t < c;
171261
var r8a4 = t < d;
172262
var r8a5 = t < e;
263+
~~~~~
264+
!!! error TS2365: Operator '<' cannot be applied to types 'T' and 'E'.
173265
var r8a6 = t < f;
174266
var r8a7 = t < g;
175267

176268
var r8b1 = a < t;
177269
var r8b2 = b < t;
270+
~~~~~
271+
!!! error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
178272
var r8b3 = c < t;
179273
var r8b4 = d < t;
180274
var r8b5 = e < t;
275+
~~~~~
276+
!!! error TS2365: Operator '<' cannot be applied to types 'E' and 'T'.
181277
var r8b6 = f < t;
182278
var r8b7 = g < t;
183279
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNumberOperand.ts(3,1): error TS2365: Operator '>=' cannot be applied to types 'number | Promise<number>' and 'number'.
2+
3+
4+
==== tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNumberOperand.ts (1 errors) ====
5+
// repro #52036
6+
declare const t1: number | Promise<number>
7+
t1 >= 0 // error
8+
~~~~~~~
9+
!!! error TS2365: Operator '>=' cannot be applied to types 'number | Promise<number>' and 'number'.
10+
!!! related TS2773 tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNumberOperand.ts:3:1: Did you forget to use 'await'?
11+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
=== tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNumberOperand.ts ===
2+
// repro #52036
3+
declare const t1: number | Promise<number>
4+
>t1 : Symbol(t1, Decl(comparisonOperatorWithNumberOperand.ts, 1, 13))
5+
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --))
6+
7+
t1 >= 0 // error
8+
>t1 : Symbol(t1, Decl(comparisonOperatorWithNumberOperand.ts, 1, 13))
9+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
=== tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNumberOperand.ts ===
2+
// repro #52036
3+
declare const t1: number | Promise<number>
4+
>t1 : number | Promise<number>
5+
6+
t1 >= 0 // error
7+
>t1 >= 0 : boolean
8+
>t1 : number | Promise<number>
9+
>0 : 0
10+

0 commit comments

Comments
 (0)