Skip to content

Commit 562240c

Browse files
committed
Merge branch 'main' into fix-48783
2 parents d219408 + 1513649 commit 562240c

10 files changed

+445
-89
lines changed

package-lock.json

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/compiler/checker.ts

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

23093+
// This like getBaseTypeOfLiteralType, but instead treats enum literals as strings/numbers instead
23094+
// of returning their enum base type (which depends on the types of other literals in the enum).
23095+
function getBaseTypeOfLiteralTypeForComparison(type: Type): Type {
23096+
return type.flags & (TypeFlags.StringLiteral | TypeFlags.TemplateLiteral | TypeFlags.StringMapping) ? stringType :
23097+
type.flags & (TypeFlags.NumberLiteral | TypeFlags.Enum) ? numberType :
23098+
type.flags & TypeFlags.BigIntLiteral ? bigintType :
23099+
type.flags & TypeFlags.BooleanLiteral ? booleanType :
23100+
type.flags & TypeFlags.Union ? mapType(type, getBaseTypeOfLiteralTypeForComparison) :
23101+
type;
23102+
}
23103+
2309323104
function getWidenedLiteralType(type: Type): Type {
2309423105
return type.flags & TypeFlags.EnumLike && isFreshLiteralType(type) ? getBaseTypeOfEnumLikeType(type as LiteralType) :
2309523106
type.flags & TypeFlags.StringLiteral && isFreshLiteralType(type) ? stringType :
@@ -36553,8 +36564,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3655336564
case SyntaxKind.LessThanEqualsToken:
3655436565
case SyntaxKind.GreaterThanEqualsToken:
3655536566
if (checkForDisallowedESSymbolOperand(operator)) {
36556-
leftType = getBaseTypeOfLiteralType(checkNonNullType(leftType, left));
36557-
rightType = getBaseTypeOfLiteralType(checkNonNullType(rightType, right));
36567+
leftType = getBaseTypeOfLiteralTypeForComparison(checkNonNullType(leftType, left));
36568+
rightType = getBaseTypeOfLiteralTypeForComparison(checkNonNullType(rightType, right));
3655836569
reportOperatorErrorUnless((left, right) => {
3655936570
if (isTypeAny(left) || isTypeAny(right)) {
3656036571
return true;

src/services/completions.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ import {
117117
isAbstractConstructorSymbol,
118118
isArrowFunction,
119119
isAssertionExpression,
120+
isAwaitExpression,
120121
isBigIntLiteral,
121122
isBinaryExpression,
122123
isBindingElement,
@@ -1319,7 +1320,9 @@ function createCompletionEntry(
13191320

13201321
awaitText += `(await ${propertyAccessToConvert.expression.getText()})`;
13211322
insertText = needsConvertPropertyAccess ? `${awaitText}${insertText}` : `${awaitText}${insertQuestionDot ? "?." : "."}${insertText}`;
1322-
replacementSpan = createTextSpanFromBounds(propertyAccessToConvert.getStart(sourceFile), propertyAccessToConvert.end);
1323+
const isInAwaitExpression = tryCast(propertyAccessToConvert.parent, isAwaitExpression);
1324+
const wrapNode = isInAwaitExpression ? propertyAccessToConvert.parent : propertyAccessToConvert.expression;
1325+
replacementSpan = createTextSpanFromBounds(wrapNode.getStart(sourceFile), propertyAccessToConvert.end);
13231326
}
13241327

13251328
if (originIsResolvedExport(origin)) {

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
Large diffs are not rendered by default.
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;
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
=== tests/cases/compiler/mixedTypeEnumComparison.ts ===
2+
const enum E {
3+
>E : Symbol(E, Decl(mixedTypeEnumComparison.ts, 0, 0))
4+
5+
S1 = "foo",
6+
>S1 : Symbol(E.S1, Decl(mixedTypeEnumComparison.ts, 0, 14))
7+
8+
S2 = "bar",
9+
>S2 : Symbol(E.S2, Decl(mixedTypeEnumComparison.ts, 1, 15))
10+
11+
N1 = 1000,
12+
>N1 : Symbol(E.N1, Decl(mixedTypeEnumComparison.ts, 2, 15))
13+
14+
N2 = 25,
15+
>N2 : Symbol(E.N2, Decl(mixedTypeEnumComparison.ts, 4, 14))
16+
}
17+
18+
declare var someNumber: number
19+
>someNumber : Symbol(someNumber, Decl(mixedTypeEnumComparison.ts, 8, 11))
20+
21+
if (someNumber > E.N2) {
22+
>someNumber : Symbol(someNumber, Decl(mixedTypeEnumComparison.ts, 8, 11))
23+
>E.N2 : Symbol(E.N2, Decl(mixedTypeEnumComparison.ts, 4, 14))
24+
>E : Symbol(E, Decl(mixedTypeEnumComparison.ts, 0, 0))
25+
>N2 : Symbol(E.N2, Decl(mixedTypeEnumComparison.ts, 4, 14))
26+
27+
someNumber = E.N2;
28+
>someNumber : Symbol(someNumber, Decl(mixedTypeEnumComparison.ts, 8, 11))
29+
>E.N2 : Symbol(E.N2, Decl(mixedTypeEnumComparison.ts, 4, 14))
30+
>E : Symbol(E, Decl(mixedTypeEnumComparison.ts, 0, 0))
31+
>N2 : Symbol(E.N2, Decl(mixedTypeEnumComparison.ts, 4, 14))
32+
}
33+
34+
declare const unionOfEnum: E.N1 | E.N2;
35+
>unionOfEnum : Symbol(unionOfEnum, Decl(mixedTypeEnumComparison.ts, 14, 13))
36+
>E : Symbol(E, Decl(mixedTypeEnumComparison.ts, 0, 0))
37+
>N1 : Symbol(E.N1, Decl(mixedTypeEnumComparison.ts, 2, 15))
38+
>E : Symbol(E, Decl(mixedTypeEnumComparison.ts, 0, 0))
39+
>N2 : Symbol(E.N2, Decl(mixedTypeEnumComparison.ts, 4, 14))
40+
41+
if (someNumber > unionOfEnum) {
42+
>someNumber : Symbol(someNumber, Decl(mixedTypeEnumComparison.ts, 8, 11))
43+
>unionOfEnum : Symbol(unionOfEnum, Decl(mixedTypeEnumComparison.ts, 14, 13))
44+
45+
someNumber = E.N2;
46+
>someNumber : Symbol(someNumber, Decl(mixedTypeEnumComparison.ts, 8, 11))
47+
>E.N2 : Symbol(E.N2, Decl(mixedTypeEnumComparison.ts, 4, 14))
48+
>E : Symbol(E, Decl(mixedTypeEnumComparison.ts, 0, 0))
49+
>N2 : Symbol(E.N2, Decl(mixedTypeEnumComparison.ts, 4, 14))
50+
}
51+
52+
declare var someString: string
53+
>someString : Symbol(someString, Decl(mixedTypeEnumComparison.ts, 20, 11))
54+
55+
if (someString > E.S1) {
56+
>someString : Symbol(someString, Decl(mixedTypeEnumComparison.ts, 20, 11))
57+
>E.S1 : Symbol(E.S1, Decl(mixedTypeEnumComparison.ts, 0, 14))
58+
>E : Symbol(E, Decl(mixedTypeEnumComparison.ts, 0, 0))
59+
>S1 : Symbol(E.S1, Decl(mixedTypeEnumComparison.ts, 0, 14))
60+
61+
someString = E.S2;
62+
>someString : Symbol(someString, Decl(mixedTypeEnumComparison.ts, 20, 11))
63+
>E.S2 : Symbol(E.S2, Decl(mixedTypeEnumComparison.ts, 1, 15))
64+
>E : Symbol(E, Decl(mixedTypeEnumComparison.ts, 0, 0))
65+
>S2 : Symbol(E.S2, Decl(mixedTypeEnumComparison.ts, 1, 15))
66+
}
67+
68+
69+
declare function someValue(): number;
70+
>someValue : Symbol(someValue, Decl(mixedTypeEnumComparison.ts, 24, 1))
71+
72+
enum E2 {
73+
>E2 : Symbol(E2, Decl(mixedTypeEnumComparison.ts, 27, 37))
74+
75+
S1 = "foo",
76+
>S1 : Symbol(E2.S1, Decl(mixedTypeEnumComparison.ts, 29, 9))
77+
78+
N1 = 1000,
79+
>N1 : Symbol(E2.N1, Decl(mixedTypeEnumComparison.ts, 30, 15))
80+
81+
C1 = someValue(),
82+
>C1 : Symbol(E2.C1, Decl(mixedTypeEnumComparison.ts, 31, 14))
83+
>someValue : Symbol(someValue, Decl(mixedTypeEnumComparison.ts, 24, 1))
84+
}
85+
86+
someString > E2.S1;
87+
>someString : Symbol(someString, Decl(mixedTypeEnumComparison.ts, 20, 11))
88+
>E2.S1 : Symbol(E2.S1, Decl(mixedTypeEnumComparison.ts, 29, 9))
89+
>E2 : Symbol(E2, Decl(mixedTypeEnumComparison.ts, 27, 37))
90+
>S1 : Symbol(E2.S1, Decl(mixedTypeEnumComparison.ts, 29, 9))
91+
92+
someNumber > E2.N1;
93+
>someNumber : Symbol(someNumber, Decl(mixedTypeEnumComparison.ts, 8, 11))
94+
>E2.N1 : Symbol(E2.N1, Decl(mixedTypeEnumComparison.ts, 30, 15))
95+
>E2 : Symbol(E2, Decl(mixedTypeEnumComparison.ts, 27, 37))
96+
>N1 : Symbol(E2.N1, Decl(mixedTypeEnumComparison.ts, 30, 15))
97+
98+
someNumber > E2.C1;
99+
>someNumber : Symbol(someNumber, Decl(mixedTypeEnumComparison.ts, 8, 11))
100+
>E2.C1 : Symbol(E2.C1, Decl(mixedTypeEnumComparison.ts, 31, 14))
101+
>E2 : Symbol(E2, Decl(mixedTypeEnumComparison.ts, 27, 37))
102+
>C1 : Symbol(E2.C1, Decl(mixedTypeEnumComparison.ts, 31, 14))
103+
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
=== tests/cases/compiler/mixedTypeEnumComparison.ts ===
2+
const enum E {
3+
>E : E
4+
5+
S1 = "foo",
6+
>S1 : E.S1
7+
>"foo" : "foo"
8+
9+
S2 = "bar",
10+
>S2 : E.S2
11+
>"bar" : "bar"
12+
13+
N1 = 1000,
14+
>N1 : E.N1
15+
>1000 : 1000
16+
17+
N2 = 25,
18+
>N2 : E.N2
19+
>25 : 25
20+
}
21+
22+
declare var someNumber: number
23+
>someNumber : number
24+
25+
if (someNumber > E.N2) {
26+
>someNumber > E.N2 : boolean
27+
>someNumber : number
28+
>E.N2 : E.N2
29+
>E : typeof E
30+
>N2 : E.N2
31+
32+
someNumber = E.N2;
33+
>someNumber = E.N2 : E.N2
34+
>someNumber : number
35+
>E.N2 : E.N2
36+
>E : typeof E
37+
>N2 : E.N2
38+
}
39+
40+
declare const unionOfEnum: E.N1 | E.N2;
41+
>unionOfEnum : E.N1 | E.N2
42+
>E : any
43+
>E : any
44+
45+
if (someNumber > unionOfEnum) {
46+
>someNumber > unionOfEnum : boolean
47+
>someNumber : number
48+
>unionOfEnum : E.N1 | E.N2
49+
50+
someNumber = E.N2;
51+
>someNumber = E.N2 : E.N2
52+
>someNumber : number
53+
>E.N2 : E.N2
54+
>E : typeof E
55+
>N2 : E.N2
56+
}
57+
58+
declare var someString: string
59+
>someString : string
60+
61+
if (someString > E.S1) {
62+
>someString > E.S1 : boolean
63+
>someString : string
64+
>E.S1 : E.S1
65+
>E : typeof E
66+
>S1 : E.S1
67+
68+
someString = E.S2;
69+
>someString = E.S2 : E.S2
70+
>someString : string
71+
>E.S2 : E.S2
72+
>E : typeof E
73+
>S2 : E.S2
74+
}
75+
76+
77+
declare function someValue(): number;
78+
>someValue : () => number
79+
80+
enum E2 {
81+
>E2 : E2
82+
83+
S1 = "foo",
84+
>S1 : E2.S1
85+
>"foo" : "foo"
86+
87+
N1 = 1000,
88+
>N1 : E2.N1
89+
>1000 : 1000
90+
91+
C1 = someValue(),
92+
>C1 : E2.C1
93+
>someValue() : number
94+
>someValue : () => number
95+
}
96+
97+
someString > E2.S1;
98+
>someString > E2.S1 : boolean
99+
>someString : string
100+
>E2.S1 : E2.S1
101+
>E2 : typeof E2
102+
>S1 : E2.S1
103+
104+
someNumber > E2.N1;
105+
>someNumber > E2.N1 : boolean
106+
>someNumber : number
107+
>E2.N1 : E2.N1
108+
>E2 : typeof E2
109+
>N1 : E2.N1
110+
111+
someNumber > E2.C1;
112+
>someNumber > E2.C1 : boolean
113+
>someNumber : number
114+
>E2.C1 : E2.C1
115+
>E2 : typeof E2
116+
>C1 : E2.C1
117+
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// @strict: true
2+
3+
const enum E {
4+
S1 = "foo",
5+
S2 = "bar",
6+
7+
N1 = 1000,
8+
N2 = 25,
9+
}
10+
11+
declare var someNumber: number
12+
13+
if (someNumber > E.N2) {
14+
someNumber = E.N2;
15+
}
16+
17+
declare const unionOfEnum: E.N1 | E.N2;
18+
19+
if (someNumber > unionOfEnum) {
20+
someNumber = E.N2;
21+
}
22+
23+
declare var someString: string
24+
25+
if (someString > E.S1) {
26+
someString = E.S2;
27+
}
28+
29+
30+
declare function someValue(): number;
31+
32+
enum E2 {
33+
S1 = "foo",
34+
N1 = 1000,
35+
C1 = someValue(),
36+
}
37+
38+
someString > E2.S1;
39+
someNumber > E2.N1;
40+
someNumber > E2.C1;

0 commit comments

Comments
 (0)