Skip to content

Commit

Permalink
noUncheckedIndexedAccess with enums Type narrowed
Browse files Browse the repository at this point in the history
  • Loading branch information
navya9singh committed Jul 14, 2022
1 parent ad4ded8 commit d0547f1
Show file tree
Hide file tree
Showing 5 changed files with 188 additions and 0 deletions.
5 changes: 5 additions & 0 deletions src/compiler/checker.ts
Expand Up @@ -15589,6 +15589,11 @@ m2: ${(this.mapper2 as unknown as DebugTypeMapper).__debugToString().split("\n")
return accessFlags & AccessFlags.IncludeUndefined ? getUnionType([indexInfo.type, undefinedType]) : indexInfo.type;
}
errorIfWritingToReadonlyIndex(indexInfo);
if (accessFlags & AccessFlags.IncludeUndefined && objectType.symbol.flags & (SymbolFlags.RegularEnum | SymbolFlags.ConstEnum)) {
if(indexType.flags & TypeFlags.EnumLiteral){
return indexInfo.type;
}
}
return accessFlags & AccessFlags.IncludeUndefined ? getUnionType([indexInfo.type, undefinedType]) : indexInfo.type;
}
if (indexType.flags & TypeFlags.Never) {
Expand Down
37 changes: 37 additions & 0 deletions tests/baselines/reference/noUncheckedIndexAccess.js
@@ -0,0 +1,37 @@
//// [noUncheckedIndexAccess.ts]
enum Meat {
Sausage,
Bacon
}
const sausage = Meat.Sausage
const valueSausage = Meat[sausage]

const bacon = Meat.Bacon
const valueBacon = Meat[bacon]

const union: Meat.Bacon | Meat.Sausage = Meat.Bacon
const valueUnion = Meat[union]

//Avoiding a false positive
const value = Meat[0]

const t = "testing"
const value2 = Meat[t]


//// [noUncheckedIndexAccess.js]
var Meat;
(function (Meat) {
Meat[Meat["Sausage"] = 0] = "Sausage";
Meat[Meat["Bacon"] = 1] = "Bacon";
})(Meat || (Meat = {}));
var sausage = Meat.Sausage;
var valueSausage = Meat[sausage];
var bacon = Meat.Bacon;
var valueBacon = Meat[bacon];
var union = Meat.Bacon;
var valueUnion = Meat[union];
//Avoiding a false positive
var value = Meat[0];
var t = "testing";
var value2 = Meat[t];
60 changes: 60 additions & 0 deletions tests/baselines/reference/noUncheckedIndexAccess.symbols
@@ -0,0 +1,60 @@
=== tests/cases/compiler/noUncheckedIndexAccess.ts ===
enum Meat {
>Meat : Symbol(Meat, Decl(noUncheckedIndexAccess.ts, 0, 0))

Sausage,
>Sausage : Symbol(Meat.Sausage, Decl(noUncheckedIndexAccess.ts, 0, 11))

Bacon
>Bacon : Symbol(Meat.Bacon, Decl(noUncheckedIndexAccess.ts, 1, 12))
}
const sausage = Meat.Sausage
>sausage : Symbol(sausage, Decl(noUncheckedIndexAccess.ts, 4, 7))
>Meat.Sausage : Symbol(Meat.Sausage, Decl(noUncheckedIndexAccess.ts, 0, 11))
>Meat : Symbol(Meat, Decl(noUncheckedIndexAccess.ts, 0, 0))
>Sausage : Symbol(Meat.Sausage, Decl(noUncheckedIndexAccess.ts, 0, 11))

const valueSausage = Meat[sausage]
>valueSausage : Symbol(valueSausage, Decl(noUncheckedIndexAccess.ts, 5, 7))
>Meat : Symbol(Meat, Decl(noUncheckedIndexAccess.ts, 0, 0))
>sausage : Symbol(sausage, Decl(noUncheckedIndexAccess.ts, 4, 7))

const bacon = Meat.Bacon
>bacon : Symbol(bacon, Decl(noUncheckedIndexAccess.ts, 7, 7))
>Meat.Bacon : Symbol(Meat.Bacon, Decl(noUncheckedIndexAccess.ts, 1, 12))
>Meat : Symbol(Meat, Decl(noUncheckedIndexAccess.ts, 0, 0))
>Bacon : Symbol(Meat.Bacon, Decl(noUncheckedIndexAccess.ts, 1, 12))

const valueBacon = Meat[bacon]
>valueBacon : Symbol(valueBacon, Decl(noUncheckedIndexAccess.ts, 8, 7))
>Meat : Symbol(Meat, Decl(noUncheckedIndexAccess.ts, 0, 0))
>bacon : Symbol(bacon, Decl(noUncheckedIndexAccess.ts, 7, 7))

const union: Meat.Bacon | Meat.Sausage = Meat.Bacon
>union : Symbol(union, Decl(noUncheckedIndexAccess.ts, 10, 7))
>Meat : Symbol(Meat, Decl(noUncheckedIndexAccess.ts, 0, 0))
>Bacon : Symbol(Meat.Bacon, Decl(noUncheckedIndexAccess.ts, 1, 12))
>Meat : Symbol(Meat, Decl(noUncheckedIndexAccess.ts, 0, 0))
>Sausage : Symbol(Meat.Sausage, Decl(noUncheckedIndexAccess.ts, 0, 11))
>Meat.Bacon : Symbol(Meat.Bacon, Decl(noUncheckedIndexAccess.ts, 1, 12))
>Meat : Symbol(Meat, Decl(noUncheckedIndexAccess.ts, 0, 0))
>Bacon : Symbol(Meat.Bacon, Decl(noUncheckedIndexAccess.ts, 1, 12))

const valueUnion = Meat[union]
>valueUnion : Symbol(valueUnion, Decl(noUncheckedIndexAccess.ts, 11, 7))
>Meat : Symbol(Meat, Decl(noUncheckedIndexAccess.ts, 0, 0))
>union : Symbol(union, Decl(noUncheckedIndexAccess.ts, 10, 7))

//Avoiding a false positive
const value = Meat[0]
>value : Symbol(value, Decl(noUncheckedIndexAccess.ts, 14, 7))
>Meat : Symbol(Meat, Decl(noUncheckedIndexAccess.ts, 0, 0))

const t = "testing"
>t : Symbol(t, Decl(noUncheckedIndexAccess.ts, 16, 7))

const value2 = Meat[t]
>value2 : Symbol(value2, Decl(noUncheckedIndexAccess.ts, 17, 7))
>Meat : Symbol(Meat, Decl(noUncheckedIndexAccess.ts, 0, 0))
>t : Symbol(t, Decl(noUncheckedIndexAccess.ts, 16, 7))

65 changes: 65 additions & 0 deletions tests/baselines/reference/noUncheckedIndexAccess.types
@@ -0,0 +1,65 @@
=== tests/cases/compiler/noUncheckedIndexAccess.ts ===
enum Meat {
>Meat : Meat

Sausage,
>Sausage : Meat.Sausage

Bacon
>Bacon : Meat.Bacon
}
const sausage = Meat.Sausage
>sausage : Meat.Sausage
>Meat.Sausage : Meat.Sausage
>Meat : typeof Meat
>Sausage : Meat.Sausage

const valueSausage = Meat[sausage]
>valueSausage : string
>Meat[sausage] : string
>Meat : typeof Meat
>sausage : Meat.Sausage

const bacon = Meat.Bacon
>bacon : Meat.Bacon
>Meat.Bacon : Meat.Bacon
>Meat : typeof Meat
>Bacon : Meat.Bacon

const valueBacon = Meat[bacon]
>valueBacon : string
>Meat[bacon] : string
>Meat : typeof Meat
>bacon : Meat.Bacon

const union: Meat.Bacon | Meat.Sausage = Meat.Bacon
>union : Meat
>Meat : any
>Meat : any
>Meat.Bacon : Meat.Bacon
>Meat : typeof Meat
>Bacon : Meat.Bacon

const valueUnion = Meat[union]
>valueUnion : string
>Meat[union] : string
>Meat : typeof Meat
>union : Meat.Bacon

//Avoiding a false positive
const value = Meat[0]
>value : string | undefined
>Meat[0] : string | undefined
>Meat : typeof Meat
>0 : 0

const t = "testing"
>t : "testing"
>"testing" : "testing"

const value2 = Meat[t]
>value2 : error
>Meat[t] : error
>Meat : typeof Meat
>t : "testing"

21 changes: 21 additions & 0 deletions tests/cases/compiler/noUncheckedIndexAccess.ts
@@ -0,0 +1,21 @@
//@noUncheckedIndexedAccess: true
//@strictNullChecks: true

enum Meat {
Sausage,
Bacon
}
const sausage = Meat.Sausage
const valueSausage = Meat[sausage]

const bacon = Meat.Bacon
const valueBacon = Meat[bacon]

const union: Meat.Bacon | Meat.Sausage = Meat.Bacon
const valueUnion = Meat[union]

//Avoiding a false positive
const value = Meat[0]

const t = "testing"
const value2 = Meat[t]

0 comments on commit d0547f1

Please sign in to comment.