Typescript: iterating an enum is now an error

Created on 28 Aug 2019  ·  6Comments  ·  Source: microsoft/TypeScript

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'.

Rescheduled Working as Intended

Most helpful comment

I confirm, it happens to me as well, I couldn't find any way to overcome this problem.

All 6 comments

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, where X is a union of the types of all numerically valued members, and an implicit numeric index signature of type string.

  • The enum object type of an enum with only string valued members has an implicit string index signature of type string and no implicit numeric index signature.

In the above, X reflects 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);
}
Was this page helpful?
0 / 5 - 0 ratings

Related issues

Antony-Jones picture Antony-Jones  ·  3Comments

jbondc picture jbondc  ·  3Comments

seanzer picture seanzer  ·  3Comments

siddjain picture siddjain  ·  3Comments

fwanicka picture fwanicka  ·  3Comments