Iterating a string enum in strict mode is not allowed since 3.6.2. Is this a breaking change or a bug?
Sample code:
// sample.ts
// compile with: `tsc --strict sample.ts`
enum DAYS { Monday = 'monday', Tuesday = 'tuesday' }
for (const a in DAYS) {
const x = DAYS[a]; // <- This is now an error
console.log(x);
}
tsc --strict sample.ts
TSC 3.5.2: Compiles OK
TSC 3.6.2: reports an error:
error TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'typeof DAYS'.
I confirm, it happens to me as well, I couldn't find any way to overcome this problem.
A workaround until the problem is solved is to use an interim object:
let _DAYS: {[propName: string]: string} = <any> DAYS;
Still having this issue.
As another alternative that feels a bit less like a work-around (at least to me) is to use type assertions after creating a new type based on the enum keys.
enum DAYS {
Monday = 'monday',
Tuesday = 'tuesday',
}
type DaysKeys = keyof typeof DAYS; //<- Equivalent to type DaysKeys = 'Monday' | 'Tuesday';
for (const a in DAYS) {
const x = DAYS[a as DaysKeys]; //<- assert type
console.log(x);
}
This was due to #31687 and was an intentional change:
Types representing object literals or modules have inferable index signatures because their exact set of properties is known. This PR implements the same behavior for types representing enum objects since these also have exact and close ended sets of properties.
The enum object type of an enum with at least one numerically valued member has an implicit string index signature of type
string | X, whereXis a union of the types of all numerically valued members, and an implicit numeric index signature of typestring.The enum object type of an enum with only string valued members has an implicit string index signature of type
stringand no implicit numeric index signature.In the above,
Xreflects the reverse mapping from strings to numeric enum values included in the generated code that initializes the enum object.
Essentially, enum declarations became stricter since the domain of possible keys is a closed set, but the type provided by for..in is just string, which is not specific enough.
The workaround is as @bdunks describes:
enum DAYS {
Monday = 'monday',
Tuesday = 'tuesday',
}
for (const a in DAYS) {
const x = DAYS[a as keyof typeof DAYS];
console.log(x);
}
Most helpful comment
I confirm, it happens to me as well, I couldn't find any way to overcome this problem.