Skip to content

Commit d79eb02

Browse files
authored
Prefer using enum literal's own base type rather than enum's base type in comparison (#52703)
1 parent 588dd82 commit d79eb02

7 files changed

+414
-82
lines changed

src/compiler/checker.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23018,6 +23018,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2301823018
return getCachedType(key) ?? setCachedType(key, mapType(type, getBaseTypeOfLiteralType));
2301923019
}
2302023020

23021+
// This like getBaseTypeOfLiteralType, but instead treats enum literals as strings/numbers instead
23022+
// of returning their enum base type (which depends on the types of other literals in the enum).
23023+
function getBaseTypeOfLiteralTypeForComparison(type: Type): Type {
23024+
return type.flags & (TypeFlags.StringLiteral | TypeFlags.TemplateLiteral | TypeFlags.StringMapping) ? stringType :
23025+
type.flags & (TypeFlags.NumberLiteral | TypeFlags.Enum) ? numberType :
23026+
type.flags & TypeFlags.BigIntLiteral ? bigintType :
23027+
type.flags & TypeFlags.BooleanLiteral ? booleanType :
23028+
type.flags & TypeFlags.Union ? mapType(type, getBaseTypeOfLiteralTypeForComparison) :
23029+
type;
23030+
}
23031+
2302123032
function getWidenedLiteralType(type: Type): Type {
2302223033
return type.flags & TypeFlags.EnumLike && isFreshLiteralType(type) ? getBaseTypeOfEnumLikeType(type as LiteralType) :
2302323034
type.flags & TypeFlags.StringLiteral && isFreshLiteralType(type) ? stringType :
@@ -36481,8 +36492,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3648136492
case SyntaxKind.LessThanEqualsToken:
3648236493
case SyntaxKind.GreaterThanEqualsToken:
3648336494
if (checkForDisallowedESSymbolOperand(operator)) {
36484-
leftType = getBaseTypeOfLiteralType(checkNonNullType(leftType, left));
36485-
rightType = getBaseTypeOfLiteralType(checkNonNullType(rightType, right));
36495+
leftType = getBaseTypeOfLiteralTypeForComparison(checkNonNullType(leftType, left));
36496+
rightType = getBaseTypeOfLiteralTypeForComparison(checkNonNullType(rightType, right));
3648636497
reportOperatorErrorUnless((left, right) => {
3648736498
if (isTypeAny(left) || isTypeAny(right)) {
3648836499
return true;

tests/baselines/reference/comparisonOperatorWithNoRelationshipPrimitiveType.errors.txt

Lines changed: 48 additions & 48 deletions
Large diffs are not rendered by default.

tests/baselines/reference/comparisonOperatorWithNoRelationshipTypeParameter.errors.txt

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -7,37 +7,37 @@ tests/cases/conformance/expressions/binaryOperators/comparisonOperator/compariso
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.
99
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'.
10+
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(26,16): error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
1111
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'.
12+
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(34,16): error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
1313
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'.
14+
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(43,16): error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
1515
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'.
16+
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(51,16): error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
1717
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'.
18+
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(60,16): error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
1919
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'.
20+
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(68,16): error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
2121
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'.
22+
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(77,16): error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
2323
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'.
24+
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(85,16): error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
2525
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'.
26+
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(94,16): error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
2727
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'.
28+
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(102,16): error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
2929
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'.
30+
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(111,16): error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
3131
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'.
32+
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(119,16): error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
3333
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'.
34+
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(128,16): error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
3535
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'.
36+
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(136,16): error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
3737
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'.
38+
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(145,16): error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
3939
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'.
40+
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(153,16): error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
4141

4242

4343
==== tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts (40 errors) ====
@@ -86,7 +86,7 @@ tests/cases/conformance/expressions/binaryOperators/comparisonOperator/compariso
8686
var r1a4 = t < d;
8787
var r1a5 = t < e;
8888
~~~~~
89-
!!! error TS2365: Operator '<' cannot be applied to types 'T' and 'E'.
89+
!!! error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
9090
var r1a6 = t < f;
9191
var r1a7 = t < g;
9292

@@ -98,7 +98,7 @@ tests/cases/conformance/expressions/binaryOperators/comparisonOperator/compariso
9898
var r1b4 = d < t;
9999
var r1b5 = e < t;
100100
~~~~~
101-
!!! error TS2365: Operator '<' cannot be applied to types 'E' and 'T'.
101+
!!! error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
102102
var r1b6 = f < t;
103103
var r1b7 = g < t;
104104

@@ -111,7 +111,7 @@ tests/cases/conformance/expressions/binaryOperators/comparisonOperator/compariso
111111
var r2a4 = t < d;
112112
var r2a5 = t < e;
113113
~~~~~
114-
!!! error TS2365: Operator '<' cannot be applied to types 'T' and 'E'.
114+
!!! error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
115115
var r2a6 = t < f;
116116
var r2a7 = t < g;
117117

@@ -123,7 +123,7 @@ tests/cases/conformance/expressions/binaryOperators/comparisonOperator/compariso
123123
var r2b4 = d < t;
124124
var r2b5 = e < t;
125125
~~~~~
126-
!!! error TS2365: Operator '<' cannot be applied to types 'E' and 'T'.
126+
!!! error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
127127
var r2b6 = f < t;
128128
var r2b7 = g < t;
129129

@@ -136,7 +136,7 @@ tests/cases/conformance/expressions/binaryOperators/comparisonOperator/compariso
136136
var r3a4 = t < d;
137137
var r3a5 = t < e;
138138
~~~~~
139-
!!! error TS2365: Operator '<' cannot be applied to types 'T' and 'E'.
139+
!!! error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
140140
var r3a6 = t < f;
141141
var r3a7 = t < g;
142142

@@ -148,7 +148,7 @@ tests/cases/conformance/expressions/binaryOperators/comparisonOperator/compariso
148148
var r3b4 = d < t;
149149
var r3b5 = e < t;
150150
~~~~~
151-
!!! error TS2365: Operator '<' cannot be applied to types 'E' and 'T'.
151+
!!! error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
152152
var r3b6 = f < t;
153153
var r3b7 = g < t;
154154

@@ -161,7 +161,7 @@ tests/cases/conformance/expressions/binaryOperators/comparisonOperator/compariso
161161
var r4a4 = t < d;
162162
var r4a5 = t < e;
163163
~~~~~
164-
!!! error TS2365: Operator '<' cannot be applied to types 'T' and 'E'.
164+
!!! error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
165165
var r4a6 = t < f;
166166
var r4a7 = t < g;
167167

@@ -173,7 +173,7 @@ tests/cases/conformance/expressions/binaryOperators/comparisonOperator/compariso
173173
var r4b4 = d < t;
174174
var r4b5 = e < t;
175175
~~~~~
176-
!!! error TS2365: Operator '<' cannot be applied to types 'E' and 'T'.
176+
!!! error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
177177
var r4b6 = f < t;
178178
var r4b7 = g < t;
179179

@@ -186,7 +186,7 @@ tests/cases/conformance/expressions/binaryOperators/comparisonOperator/compariso
186186
var r5a4 = t < d;
187187
var r5a5 = t < e;
188188
~~~~~
189-
!!! error TS2365: Operator '<' cannot be applied to types 'T' and 'E'.
189+
!!! error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
190190
var r5a6 = t < f;
191191
var r5a7 = t < g;
192192

@@ -198,7 +198,7 @@ tests/cases/conformance/expressions/binaryOperators/comparisonOperator/compariso
198198
var r5b4 = d < t;
199199
var r5b5 = e < t;
200200
~~~~~
201-
!!! error TS2365: Operator '<' cannot be applied to types 'E' and 'T'.
201+
!!! error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
202202
var r5b6 = f < t;
203203
var r5b7 = g < t;
204204

@@ -211,7 +211,7 @@ tests/cases/conformance/expressions/binaryOperators/comparisonOperator/compariso
211211
var r6a4 = t < d;
212212
var r6a5 = t < e;
213213
~~~~~
214-
!!! error TS2365: Operator '<' cannot be applied to types 'T' and 'E'.
214+
!!! error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
215215
var r6a6 = t < f;
216216
var r6a7 = t < g;
217217

@@ -223,7 +223,7 @@ tests/cases/conformance/expressions/binaryOperators/comparisonOperator/compariso
223223
var r6b4 = d < t;
224224
var r6b5 = e < t;
225225
~~~~~
226-
!!! error TS2365: Operator '<' cannot be applied to types 'E' and 'T'.
226+
!!! error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
227227
var r6b6 = f < t;
228228
var r6b7 = g < t;
229229

@@ -236,7 +236,7 @@ tests/cases/conformance/expressions/binaryOperators/comparisonOperator/compariso
236236
var r7a4 = t < d;
237237
var r7a5 = t < e;
238238
~~~~~
239-
!!! error TS2365: Operator '<' cannot be applied to types 'T' and 'E'.
239+
!!! error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
240240
var r7a6 = t < f;
241241
var r7a7 = t < g;
242242

@@ -248,7 +248,7 @@ tests/cases/conformance/expressions/binaryOperators/comparisonOperator/compariso
248248
var r7b4 = d < t;
249249
var r7b5 = e < t;
250250
~~~~~
251-
!!! error TS2365: Operator '<' cannot be applied to types 'E' and 'T'.
251+
!!! error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
252252
var r7b6 = f < t;
253253
var r7b7 = g < t;
254254

@@ -261,7 +261,7 @@ tests/cases/conformance/expressions/binaryOperators/comparisonOperator/compariso
261261
var r8a4 = t < d;
262262
var r8a5 = t < e;
263263
~~~~~
264-
!!! error TS2365: Operator '<' cannot be applied to types 'T' and 'E'.
264+
!!! error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
265265
var r8a6 = t < f;
266266
var r8a7 = t < g;
267267

@@ -273,7 +273,7 @@ tests/cases/conformance/expressions/binaryOperators/comparisonOperator/compariso
273273
var r8b4 = d < t;
274274
var r8b5 = e < t;
275275
~~~~~
276-
!!! error TS2365: Operator '<' cannot be applied to types 'E' and 'T'.
276+
!!! error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
277277
var r8b6 = f < t;
278278
var r8b7 = g < t;
279279
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
//// [mixedTypeEnumComparison.ts]
2+
const enum E {
3+
S1 = "foo",
4+
S2 = "bar",
5+
6+
N1 = 1000,
7+
N2 = 25,
8+
}
9+
10+
declare var someNumber: number
11+
12+
if (someNumber > E.N2) {
13+
someNumber = E.N2;
14+
}
15+
16+
declare const unionOfEnum: E.N1 | E.N2;
17+
18+
if (someNumber > unionOfEnum) {
19+
someNumber = E.N2;
20+
}
21+
22+
declare var someString: string
23+
24+
if (someString > E.S1) {
25+
someString = E.S2;
26+
}
27+
28+
29+
declare function someValue(): number;
30+
31+
enum E2 {
32+
S1 = "foo",
33+
N1 = 1000,
34+
C1 = someValue(),
35+
}
36+
37+
someString > E2.S1;
38+
someNumber > E2.N1;
39+
someNumber > E2.C1;
40+
41+
42+
//// [mixedTypeEnumComparison.js]
43+
"use strict";
44+
if (someNumber > 25 /* E.N2 */) {
45+
someNumber = 25 /* E.N2 */;
46+
}
47+
if (someNumber > unionOfEnum) {
48+
someNumber = 25 /* E.N2 */;
49+
}
50+
if (someString > "foo" /* E.S1 */) {
51+
someString = "bar" /* E.S2 */;
52+
}
53+
var E2;
54+
(function (E2) {
55+
E2["S1"] = "foo";
56+
E2[E2["N1"] = 1000] = "N1";
57+
E2[E2["C1"] = someValue()] = "C1";
58+
})(E2 || (E2 = {}));
59+
someString > E2.S1;
60+
someNumber > E2.N1;
61+
someNumber > E2.C1;

0 commit comments

Comments
 (0)