Skip to content

Commit d0547f1

Browse files
committed
noUncheckedIndexedAccess with enums Type narrowed
1 parent ad4ded8 commit d0547f1

File tree

5 files changed

+188
-0
lines changed

5 files changed

+188
-0
lines changed

src/compiler/checker.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15589,6 +15589,11 @@ m2: ${(this.mapper2 as unknown as DebugTypeMapper).__debugToString().split("\n")
1558915589
return accessFlags & AccessFlags.IncludeUndefined ? getUnionType([indexInfo.type, undefinedType]) : indexInfo.type;
1559015590
}
1559115591
errorIfWritingToReadonlyIndex(indexInfo);
15592+
if (accessFlags & AccessFlags.IncludeUndefined && objectType.symbol.flags & (SymbolFlags.RegularEnum | SymbolFlags.ConstEnum)) {
15593+
if(indexType.flags & TypeFlags.EnumLiteral){
15594+
return indexInfo.type;
15595+
}
15596+
}
1559215597
return accessFlags & AccessFlags.IncludeUndefined ? getUnionType([indexInfo.type, undefinedType]) : indexInfo.type;
1559315598
}
1559415599
if (indexType.flags & TypeFlags.Never) {
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//// [noUncheckedIndexAccess.ts]
2+
enum Meat {
3+
Sausage,
4+
Bacon
5+
}
6+
const sausage = Meat.Sausage
7+
const valueSausage = Meat[sausage]
8+
9+
const bacon = Meat.Bacon
10+
const valueBacon = Meat[bacon]
11+
12+
const union: Meat.Bacon | Meat.Sausage = Meat.Bacon
13+
const valueUnion = Meat[union]
14+
15+
//Avoiding a false positive
16+
const value = Meat[0]
17+
18+
const t = "testing"
19+
const value2 = Meat[t]
20+
21+
22+
//// [noUncheckedIndexAccess.js]
23+
var Meat;
24+
(function (Meat) {
25+
Meat[Meat["Sausage"] = 0] = "Sausage";
26+
Meat[Meat["Bacon"] = 1] = "Bacon";
27+
})(Meat || (Meat = {}));
28+
var sausage = Meat.Sausage;
29+
var valueSausage = Meat[sausage];
30+
var bacon = Meat.Bacon;
31+
var valueBacon = Meat[bacon];
32+
var union = Meat.Bacon;
33+
var valueUnion = Meat[union];
34+
//Avoiding a false positive
35+
var value = Meat[0];
36+
var t = "testing";
37+
var value2 = Meat[t];
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
=== tests/cases/compiler/noUncheckedIndexAccess.ts ===
2+
enum Meat {
3+
>Meat : Symbol(Meat, Decl(noUncheckedIndexAccess.ts, 0, 0))
4+
5+
Sausage,
6+
>Sausage : Symbol(Meat.Sausage, Decl(noUncheckedIndexAccess.ts, 0, 11))
7+
8+
Bacon
9+
>Bacon : Symbol(Meat.Bacon, Decl(noUncheckedIndexAccess.ts, 1, 12))
10+
}
11+
const sausage = Meat.Sausage
12+
>sausage : Symbol(sausage, Decl(noUncheckedIndexAccess.ts, 4, 7))
13+
>Meat.Sausage : Symbol(Meat.Sausage, Decl(noUncheckedIndexAccess.ts, 0, 11))
14+
>Meat : Symbol(Meat, Decl(noUncheckedIndexAccess.ts, 0, 0))
15+
>Sausage : Symbol(Meat.Sausage, Decl(noUncheckedIndexAccess.ts, 0, 11))
16+
17+
const valueSausage = Meat[sausage]
18+
>valueSausage : Symbol(valueSausage, Decl(noUncheckedIndexAccess.ts, 5, 7))
19+
>Meat : Symbol(Meat, Decl(noUncheckedIndexAccess.ts, 0, 0))
20+
>sausage : Symbol(sausage, Decl(noUncheckedIndexAccess.ts, 4, 7))
21+
22+
const bacon = Meat.Bacon
23+
>bacon : Symbol(bacon, Decl(noUncheckedIndexAccess.ts, 7, 7))
24+
>Meat.Bacon : Symbol(Meat.Bacon, Decl(noUncheckedIndexAccess.ts, 1, 12))
25+
>Meat : Symbol(Meat, Decl(noUncheckedIndexAccess.ts, 0, 0))
26+
>Bacon : Symbol(Meat.Bacon, Decl(noUncheckedIndexAccess.ts, 1, 12))
27+
28+
const valueBacon = Meat[bacon]
29+
>valueBacon : Symbol(valueBacon, Decl(noUncheckedIndexAccess.ts, 8, 7))
30+
>Meat : Symbol(Meat, Decl(noUncheckedIndexAccess.ts, 0, 0))
31+
>bacon : Symbol(bacon, Decl(noUncheckedIndexAccess.ts, 7, 7))
32+
33+
const union: Meat.Bacon | Meat.Sausage = Meat.Bacon
34+
>union : Symbol(union, Decl(noUncheckedIndexAccess.ts, 10, 7))
35+
>Meat : Symbol(Meat, Decl(noUncheckedIndexAccess.ts, 0, 0))
36+
>Bacon : Symbol(Meat.Bacon, Decl(noUncheckedIndexAccess.ts, 1, 12))
37+
>Meat : Symbol(Meat, Decl(noUncheckedIndexAccess.ts, 0, 0))
38+
>Sausage : Symbol(Meat.Sausage, Decl(noUncheckedIndexAccess.ts, 0, 11))
39+
>Meat.Bacon : Symbol(Meat.Bacon, Decl(noUncheckedIndexAccess.ts, 1, 12))
40+
>Meat : Symbol(Meat, Decl(noUncheckedIndexAccess.ts, 0, 0))
41+
>Bacon : Symbol(Meat.Bacon, Decl(noUncheckedIndexAccess.ts, 1, 12))
42+
43+
const valueUnion = Meat[union]
44+
>valueUnion : Symbol(valueUnion, Decl(noUncheckedIndexAccess.ts, 11, 7))
45+
>Meat : Symbol(Meat, Decl(noUncheckedIndexAccess.ts, 0, 0))
46+
>union : Symbol(union, Decl(noUncheckedIndexAccess.ts, 10, 7))
47+
48+
//Avoiding a false positive
49+
const value = Meat[0]
50+
>value : Symbol(value, Decl(noUncheckedIndexAccess.ts, 14, 7))
51+
>Meat : Symbol(Meat, Decl(noUncheckedIndexAccess.ts, 0, 0))
52+
53+
const t = "testing"
54+
>t : Symbol(t, Decl(noUncheckedIndexAccess.ts, 16, 7))
55+
56+
const value2 = Meat[t]
57+
>value2 : Symbol(value2, Decl(noUncheckedIndexAccess.ts, 17, 7))
58+
>Meat : Symbol(Meat, Decl(noUncheckedIndexAccess.ts, 0, 0))
59+
>t : Symbol(t, Decl(noUncheckedIndexAccess.ts, 16, 7))
60+
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
=== tests/cases/compiler/noUncheckedIndexAccess.ts ===
2+
enum Meat {
3+
>Meat : Meat
4+
5+
Sausage,
6+
>Sausage : Meat.Sausage
7+
8+
Bacon
9+
>Bacon : Meat.Bacon
10+
}
11+
const sausage = Meat.Sausage
12+
>sausage : Meat.Sausage
13+
>Meat.Sausage : Meat.Sausage
14+
>Meat : typeof Meat
15+
>Sausage : Meat.Sausage
16+
17+
const valueSausage = Meat[sausage]
18+
>valueSausage : string
19+
>Meat[sausage] : string
20+
>Meat : typeof Meat
21+
>sausage : Meat.Sausage
22+
23+
const bacon = Meat.Bacon
24+
>bacon : Meat.Bacon
25+
>Meat.Bacon : Meat.Bacon
26+
>Meat : typeof Meat
27+
>Bacon : Meat.Bacon
28+
29+
const valueBacon = Meat[bacon]
30+
>valueBacon : string
31+
>Meat[bacon] : string
32+
>Meat : typeof Meat
33+
>bacon : Meat.Bacon
34+
35+
const union: Meat.Bacon | Meat.Sausage = Meat.Bacon
36+
>union : Meat
37+
>Meat : any
38+
>Meat : any
39+
>Meat.Bacon : Meat.Bacon
40+
>Meat : typeof Meat
41+
>Bacon : Meat.Bacon
42+
43+
const valueUnion = Meat[union]
44+
>valueUnion : string
45+
>Meat[union] : string
46+
>Meat : typeof Meat
47+
>union : Meat.Bacon
48+
49+
//Avoiding a false positive
50+
const value = Meat[0]
51+
>value : string | undefined
52+
>Meat[0] : string | undefined
53+
>Meat : typeof Meat
54+
>0 : 0
55+
56+
const t = "testing"
57+
>t : "testing"
58+
>"testing" : "testing"
59+
60+
const value2 = Meat[t]
61+
>value2 : error
62+
>Meat[t] : error
63+
>Meat : typeof Meat
64+
>t : "testing"
65+
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//@noUncheckedIndexedAccess: true
2+
//@strictNullChecks: true
3+
4+
enum Meat {
5+
Sausage,
6+
Bacon
7+
}
8+
const sausage = Meat.Sausage
9+
const valueSausage = Meat[sausage]
10+
11+
const bacon = Meat.Bacon
12+
const valueBacon = Meat[bacon]
13+
14+
const union: Meat.Bacon | Meat.Sausage = Meat.Bacon
15+
const valueUnion = Meat[union]
16+
17+
//Avoiding a false positive
18+
const value = Meat[0]
19+
20+
const t = "testing"
21+
const value2 = Meat[t]

0 commit comments

Comments
 (0)