Skip to content

Commit f918bd9

Browse files
authored
Exclude enum/number compatibility rule from comparable relation (#42472)
* Exclude old number/enum literal compatibility rule from comparable relation * Add tests * Accept new baselines
1 parent ba56fca commit f918bd9

File tree

6 files changed

+373
-1
lines changed

6 files changed

+373
-1
lines changed

Diff for: src/compiler/checker.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -16923,7 +16923,7 @@ namespace ts {
1692316923
// numeric enum literal type. This rule exists for backwards compatibility reasons because
1692416924
// bit-flag enum types sometimes look like literal enum types with numeric literal values.
1692516925
if (s & (TypeFlags.Number | TypeFlags.NumberLiteral) && !(s & TypeFlags.EnumLiteral) && (
16926-
t & TypeFlags.Enum || t & TypeFlags.NumberLiteral && t & TypeFlags.EnumLiteral)) return true;
16926+
t & TypeFlags.Enum || relation === assignableRelation && t & TypeFlags.NumberLiteral && t & TypeFlags.EnumLiteral)) return true;
1692716927
}
1692816928
return false;
1692916929
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
tests/cases/conformance/types/typeRelationships/comparable/equalityWithEnumTypes.ts(14,9): error TS2367: This condition will always return 'true' since the types 'E1' and '0' have no overlap.
2+
tests/cases/conformance/types/typeRelationships/comparable/equalityWithEnumTypes.ts(23,9): error TS2367: This condition will always return 'true' since the types 'E1' and '3' have no overlap.
3+
4+
5+
==== tests/cases/conformance/types/typeRelationships/comparable/equalityWithEnumTypes.ts (2 errors) ====
6+
// Literal enum type
7+
enum E1 {
8+
a = 1,
9+
b = 2,
10+
}
11+
12+
// Numeric enum type
13+
enum E2 {
14+
a = 1 << 0,
15+
b = 1 << 1
16+
}
17+
18+
function f1(v: E1) {
19+
if (v !== 0) { // Error
20+
~~~~~~~
21+
!!! error TS2367: This condition will always return 'true' since the types 'E1' and '0' have no overlap.
22+
v;
23+
}
24+
if (v !== 1) {
25+
v;
26+
}
27+
if (v !== 2) {
28+
v;
29+
}
30+
if (v !== 3) { // Error
31+
~~~~~~~
32+
!!! error TS2367: This condition will always return 'true' since the types 'E1' and '3' have no overlap.
33+
v;
34+
}
35+
}
36+
37+
function f2(v: E2) {
38+
if (v !== 0) {
39+
v;
40+
}
41+
if (v !== 1) {
42+
v;
43+
}
44+
if (v !== 2) {
45+
v;
46+
}
47+
if (v !== 3) {
48+
v;
49+
}
50+
}
51+

Diff for: tests/baselines/reference/equalityWithEnumTypes.js

+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
//// [equalityWithEnumTypes.ts]
2+
// Literal enum type
3+
enum E1 {
4+
a = 1,
5+
b = 2,
6+
}
7+
8+
// Numeric enum type
9+
enum E2 {
10+
a = 1 << 0,
11+
b = 1 << 1
12+
}
13+
14+
function f1(v: E1) {
15+
if (v !== 0) { // Error
16+
v;
17+
}
18+
if (v !== 1) {
19+
v;
20+
}
21+
if (v !== 2) {
22+
v;
23+
}
24+
if (v !== 3) { // Error
25+
v;
26+
}
27+
}
28+
29+
function f2(v: E2) {
30+
if (v !== 0) {
31+
v;
32+
}
33+
if (v !== 1) {
34+
v;
35+
}
36+
if (v !== 2) {
37+
v;
38+
}
39+
if (v !== 3) {
40+
v;
41+
}
42+
}
43+
44+
45+
//// [equalityWithEnumTypes.js]
46+
"use strict";
47+
// Literal enum type
48+
var E1;
49+
(function (E1) {
50+
E1[E1["a"] = 1] = "a";
51+
E1[E1["b"] = 2] = "b";
52+
})(E1 || (E1 = {}));
53+
// Numeric enum type
54+
var E2;
55+
(function (E2) {
56+
E2[E2["a"] = 1] = "a";
57+
E2[E2["b"] = 2] = "b";
58+
})(E2 || (E2 = {}));
59+
function f1(v) {
60+
if (v !== 0) { // Error
61+
v;
62+
}
63+
if (v !== 1) {
64+
v;
65+
}
66+
if (v !== 2) {
67+
v;
68+
}
69+
if (v !== 3) { // Error
70+
v;
71+
}
72+
}
73+
function f2(v) {
74+
if (v !== 0) {
75+
v;
76+
}
77+
if (v !== 1) {
78+
v;
79+
}
80+
if (v !== 2) {
81+
v;
82+
}
83+
if (v !== 3) {
84+
v;
85+
}
86+
}
+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
=== tests/cases/conformance/types/typeRelationships/comparable/equalityWithEnumTypes.ts ===
2+
// Literal enum type
3+
enum E1 {
4+
>E1 : Symbol(E1, Decl(equalityWithEnumTypes.ts, 0, 0))
5+
6+
a = 1,
7+
>a : Symbol(E1.a, Decl(equalityWithEnumTypes.ts, 1, 9))
8+
9+
b = 2,
10+
>b : Symbol(E1.b, Decl(equalityWithEnumTypes.ts, 2, 10))
11+
}
12+
13+
// Numeric enum type
14+
enum E2 {
15+
>E2 : Symbol(E2, Decl(equalityWithEnumTypes.ts, 4, 1))
16+
17+
a = 1 << 0,
18+
>a : Symbol(E2.a, Decl(equalityWithEnumTypes.ts, 7, 9))
19+
20+
b = 1 << 1
21+
>b : Symbol(E2.b, Decl(equalityWithEnumTypes.ts, 8, 15))
22+
}
23+
24+
function f1(v: E1) {
25+
>f1 : Symbol(f1, Decl(equalityWithEnumTypes.ts, 10, 1))
26+
>v : Symbol(v, Decl(equalityWithEnumTypes.ts, 12, 12))
27+
>E1 : Symbol(E1, Decl(equalityWithEnumTypes.ts, 0, 0))
28+
29+
if (v !== 0) { // Error
30+
>v : Symbol(v, Decl(equalityWithEnumTypes.ts, 12, 12))
31+
32+
v;
33+
>v : Symbol(v, Decl(equalityWithEnumTypes.ts, 12, 12))
34+
}
35+
if (v !== 1) {
36+
>v : Symbol(v, Decl(equalityWithEnumTypes.ts, 12, 12))
37+
38+
v;
39+
>v : Symbol(v, Decl(equalityWithEnumTypes.ts, 12, 12))
40+
}
41+
if (v !== 2) {
42+
>v : Symbol(v, Decl(equalityWithEnumTypes.ts, 12, 12))
43+
44+
v;
45+
>v : Symbol(v, Decl(equalityWithEnumTypes.ts, 12, 12))
46+
}
47+
if (v !== 3) { // Error
48+
>v : Symbol(v, Decl(equalityWithEnumTypes.ts, 12, 12))
49+
50+
v;
51+
>v : Symbol(v, Decl(equalityWithEnumTypes.ts, 12, 12))
52+
}
53+
}
54+
55+
function f2(v: E2) {
56+
>f2 : Symbol(f2, Decl(equalityWithEnumTypes.ts, 25, 1))
57+
>v : Symbol(v, Decl(equalityWithEnumTypes.ts, 27, 12))
58+
>E2 : Symbol(E2, Decl(equalityWithEnumTypes.ts, 4, 1))
59+
60+
if (v !== 0) {
61+
>v : Symbol(v, Decl(equalityWithEnumTypes.ts, 27, 12))
62+
63+
v;
64+
>v : Symbol(v, Decl(equalityWithEnumTypes.ts, 27, 12))
65+
}
66+
if (v !== 1) {
67+
>v : Symbol(v, Decl(equalityWithEnumTypes.ts, 27, 12))
68+
69+
v;
70+
>v : Symbol(v, Decl(equalityWithEnumTypes.ts, 27, 12))
71+
}
72+
if (v !== 2) {
73+
>v : Symbol(v, Decl(equalityWithEnumTypes.ts, 27, 12))
74+
75+
v;
76+
>v : Symbol(v, Decl(equalityWithEnumTypes.ts, 27, 12))
77+
}
78+
if (v !== 3) {
79+
>v : Symbol(v, Decl(equalityWithEnumTypes.ts, 27, 12))
80+
81+
v;
82+
>v : Symbol(v, Decl(equalityWithEnumTypes.ts, 27, 12))
83+
}
84+
}
85+
+107
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
=== tests/cases/conformance/types/typeRelationships/comparable/equalityWithEnumTypes.ts ===
2+
// Literal enum type
3+
enum E1 {
4+
>E1 : E1
5+
6+
a = 1,
7+
>a : E1.a
8+
>1 : 1
9+
10+
b = 2,
11+
>b : E1.b
12+
>2 : 2
13+
}
14+
15+
// Numeric enum type
16+
enum E2 {
17+
>E2 : E2
18+
19+
a = 1 << 0,
20+
>a : E2
21+
>1 << 0 : number
22+
>1 : 1
23+
>0 : 0
24+
25+
b = 1 << 1
26+
>b : E2
27+
>1 << 1 : number
28+
>1 : 1
29+
>1 : 1
30+
}
31+
32+
function f1(v: E1) {
33+
>f1 : (v: E1) => void
34+
>v : E1
35+
36+
if (v !== 0) { // Error
37+
>v !== 0 : boolean
38+
>v : E1
39+
>0 : 0
40+
41+
v;
42+
>v : E1
43+
}
44+
if (v !== 1) {
45+
>v !== 1 : boolean
46+
>v : E1
47+
>1 : 1
48+
49+
v;
50+
>v : E1.b
51+
}
52+
if (v !== 2) {
53+
>v !== 2 : boolean
54+
>v : E1
55+
>2 : 2
56+
57+
v;
58+
>v : E1.a
59+
}
60+
if (v !== 3) { // Error
61+
>v !== 3 : boolean
62+
>v : E1
63+
>3 : 3
64+
65+
v;
66+
>v : E1
67+
}
68+
}
69+
70+
function f2(v: E2) {
71+
>f2 : (v: E2) => void
72+
>v : E2
73+
74+
if (v !== 0) {
75+
>v !== 0 : boolean
76+
>v : E2
77+
>0 : 0
78+
79+
v;
80+
>v : E2
81+
}
82+
if (v !== 1) {
83+
>v !== 1 : boolean
84+
>v : E2
85+
>1 : 1
86+
87+
v;
88+
>v : E2
89+
}
90+
if (v !== 2) {
91+
>v !== 2 : boolean
92+
>v : E2
93+
>2 : 2
94+
95+
v;
96+
>v : E2
97+
}
98+
if (v !== 3) {
99+
>v !== 3 : boolean
100+
>v : E2
101+
>3 : 3
102+
103+
v;
104+
>v : E2
105+
}
106+
}
107+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// @strict: true
2+
3+
// Literal enum type
4+
enum E1 {
5+
a = 1,
6+
b = 2,
7+
}
8+
9+
// Numeric enum type
10+
enum E2 {
11+
a = 1 << 0,
12+
b = 1 << 1
13+
}
14+
15+
function f1(v: E1) {
16+
if (v !== 0) { // Error
17+
v;
18+
}
19+
if (v !== 1) {
20+
v;
21+
}
22+
if (v !== 2) {
23+
v;
24+
}
25+
if (v !== 3) { // Error
26+
v;
27+
}
28+
}
29+
30+
function f2(v: E2) {
31+
if (v !== 0) {
32+
v;
33+
}
34+
if (v !== 1) {
35+
v;
36+
}
37+
if (v !== 2) {
38+
v;
39+
}
40+
if (v !== 3) {
41+
v;
42+
}
43+
}

0 commit comments

Comments
 (0)