mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-14 19:16:17 -06:00
Merge pull request #49912 from microsoft/fix/47508
fix(47508): noUncheckedIndexedAccess with enums Type narrowed
This commit is contained in:
commit
bc9cbbef42
@ -15814,7 +15814,18 @@ namespace ts {
|
||||
return accessFlags & AccessFlags.IncludeUndefined ? getUnionType([indexInfo.type, undefinedType]) : indexInfo.type;
|
||||
}
|
||||
errorIfWritingToReadonlyIndex(indexInfo);
|
||||
return accessFlags & AccessFlags.IncludeUndefined ? getUnionType([indexInfo.type, undefinedType]) : indexInfo.type;
|
||||
// When accessing an enum object with its own type,
|
||||
// e.g. E[E.A] for enum E { A }, undefined shouldn't
|
||||
// be included in the result type
|
||||
if ((accessFlags & AccessFlags.IncludeUndefined) &&
|
||||
!(objectType.symbol &&
|
||||
objectType.symbol.flags & (SymbolFlags.RegularEnum | SymbolFlags.ConstEnum) &&
|
||||
(indexType.symbol &&
|
||||
indexType.flags & TypeFlags.EnumLiteral &&
|
||||
getParentOfSymbol(indexType.symbol) === objectType.symbol))) {
|
||||
return getUnionType([indexInfo.type, undefinedType]);
|
||||
}
|
||||
return indexInfo.type;
|
||||
}
|
||||
if (indexType.flags & TypeFlags.Never) {
|
||||
return neverType;
|
||||
|
||||
58
tests/baselines/reference/noUncheckedIndexAccess.js
Normal file
58
tests/baselines/reference/noUncheckedIndexAccess.js
Normal file
@ -0,0 +1,58 @@
|
||||
//// [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 valueUndefined = "testing"
|
||||
const value2 = Meat[valueUndefined]
|
||||
|
||||
enum A {
|
||||
a, b, c
|
||||
}
|
||||
enum B {
|
||||
x, y, z
|
||||
}
|
||||
|
||||
const value3 = A[B.x];
|
||||
|
||||
//// [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 valueUndefined = "testing";
|
||||
var value2 = Meat[valueUndefined];
|
||||
var A;
|
||||
(function (A) {
|
||||
A[A["a"] = 0] = "a";
|
||||
A[A["b"] = 1] = "b";
|
||||
A[A["c"] = 2] = "c";
|
||||
})(A || (A = {}));
|
||||
var B;
|
||||
(function (B) {
|
||||
B[B["x"] = 0] = "x";
|
||||
B[B["y"] = 1] = "y";
|
||||
B[B["z"] = 2] = "z";
|
||||
})(B || (B = {}));
|
||||
var value3 = A[B.x];
|
||||
84
tests/baselines/reference/noUncheckedIndexAccess.symbols
Normal file
84
tests/baselines/reference/noUncheckedIndexAccess.symbols
Normal file
@ -0,0 +1,84 @@
|
||||
=== 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 valueUndefined = "testing"
|
||||
>valueUndefined : Symbol(valueUndefined, Decl(noUncheckedIndexAccess.ts, 16, 7))
|
||||
|
||||
const value2 = Meat[valueUndefined]
|
||||
>value2 : Symbol(value2, Decl(noUncheckedIndexAccess.ts, 17, 7))
|
||||
>Meat : Symbol(Meat, Decl(noUncheckedIndexAccess.ts, 0, 0))
|
||||
>valueUndefined : Symbol(valueUndefined, Decl(noUncheckedIndexAccess.ts, 16, 7))
|
||||
|
||||
enum A {
|
||||
>A : Symbol(A, Decl(noUncheckedIndexAccess.ts, 17, 37))
|
||||
|
||||
a, b, c
|
||||
>a : Symbol(A.a, Decl(noUncheckedIndexAccess.ts, 19, 10))
|
||||
>b : Symbol(A.b, Decl(noUncheckedIndexAccess.ts, 20, 6))
|
||||
>c : Symbol(A.c, Decl(noUncheckedIndexAccess.ts, 20, 9))
|
||||
}
|
||||
enum B {
|
||||
>B : Symbol(B, Decl(noUncheckedIndexAccess.ts, 21, 3))
|
||||
|
||||
x, y, z
|
||||
>x : Symbol(B.x, Decl(noUncheckedIndexAccess.ts, 22, 10))
|
||||
>y : Symbol(B.y, Decl(noUncheckedIndexAccess.ts, 23, 6))
|
||||
>z : Symbol(B.z, Decl(noUncheckedIndexAccess.ts, 23, 9))
|
||||
}
|
||||
|
||||
const value3 = A[B.x];
|
||||
>value3 : Symbol(value3, Decl(noUncheckedIndexAccess.ts, 26, 7))
|
||||
>A : Symbol(A, Decl(noUncheckedIndexAccess.ts, 17, 37))
|
||||
>B.x : Symbol(B.x, Decl(noUncheckedIndexAccess.ts, 22, 10))
|
||||
>B : Symbol(B, Decl(noUncheckedIndexAccess.ts, 21, 3))
|
||||
>x : Symbol(B.x, Decl(noUncheckedIndexAccess.ts, 22, 10))
|
||||
|
||||
90
tests/baselines/reference/noUncheckedIndexAccess.types
Normal file
90
tests/baselines/reference/noUncheckedIndexAccess.types
Normal file
@ -0,0 +1,90 @@
|
||||
=== 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 valueUndefined = "testing"
|
||||
>valueUndefined : "testing"
|
||||
>"testing" : "testing"
|
||||
|
||||
const value2 = Meat[valueUndefined]
|
||||
>value2 : error
|
||||
>Meat[valueUndefined] : error
|
||||
>Meat : typeof Meat
|
||||
>valueUndefined : "testing"
|
||||
|
||||
enum A {
|
||||
>A : A
|
||||
|
||||
a, b, c
|
||||
>a : A.a
|
||||
>b : A.b
|
||||
>c : A.c
|
||||
}
|
||||
enum B {
|
||||
>B : B
|
||||
|
||||
x, y, z
|
||||
>x : B.x
|
||||
>y : B.y
|
||||
>z : B.z
|
||||
}
|
||||
|
||||
const value3 = A[B.x];
|
||||
>value3 : string | undefined
|
||||
>A[B.x] : string | undefined
|
||||
>A : typeof A
|
||||
>B.x : B.x
|
||||
>B : typeof B
|
||||
>x : B.x
|
||||
|
||||
30
tests/cases/compiler/noUncheckedIndexAccess.ts
Normal file
30
tests/cases/compiler/noUncheckedIndexAccess.ts
Normal file
@ -0,0 +1,30 @@
|
||||
//@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 valueUndefined = "testing"
|
||||
const value2 = Meat[valueUndefined]
|
||||
|
||||
enum A {
|
||||
a, b, c
|
||||
}
|
||||
enum B {
|
||||
x, y, z
|
||||
}
|
||||
|
||||
const value3 = A[B.x];
|
||||
Loading…
x
Reference in New Issue
Block a user