kentor
kentor

Reputation: 18524

Iterate on string enum

I must be missing something, but I found several ways to iterate through an Enum but not on a string enum.

The following enum is given:

export enum Locales {
  En = 'en',
  Fr = 'fr',
  De = 'de',
  Es = 'es',
  It = 'it',
  Nl = 'nl',
  No = 'no',
  Tr = 'tr',
}

What I want to achieve:

I want to iterate on that string enum so that I get the values (!). What I've tried:

for (const key of Object.keys(Locales)) {
  const locale: string = Locales[key];
  console.log(locale); // Should print 'en', 'fr' and so on
}

The problem with above code:

Due to the strict tsconfig (which doesn't allow implicit anys) I can not compile this to javascript. Since this is not my project I can not change this tsconfig either. It highlights the key variable at Locales[key] and the error makes sense to me:

[ts] Element implicitly has an 'any' type because index expression is not of type 'number'.

The question:

What's the proper way iterating through a string enum to get it's values with Typescript 2.6+?

Upvotes: 17

Views: 19938

Answers (5)

ViPuL5
ViPuL5

Reputation: 613

 const entries = Object.entries(Locales);
  let LocalesArray= [];
  entries.forEach((type) => {
    LocalesArray.push({ key: type[0], name: type[1] });
  });

Simple way to iterate over enum values and convert them into object array.

Upvotes: 0

cthulhu
cthulhu

Reputation: 3169

Adding to this question because I was looking for a solution.

The best solution is to use Object.values() https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/values

Object.values(Locales).forEach((locale) => console.log(locale));

// or

for (const locale of Object.values(Locales)) {
  console.log(locale);
}

Also consider Object.entries() to get both the keys and values of a string value enum.

Upvotes: 1

Dany Gagnon
Dany Gagnon

Reputation: 112

Lodash

Lodash is a good option to use since it is easy to use and provides a easy to understand api. From the lodash methods, forIn is the option you're looking for. To get typescript declaration files, you can install:

npm install @types/lodash

With the forIn method, you get the value and the key of Locales object.

import { forIn } from 'lodash'

enum Locales {
  En = 'en',
  Fr = 'fr'
  // ...
}

forIn(Locales, (value, key) => console.log(value, key))

Upvotes: 3

kentor
kentor

Reputation: 18524

@Artem and @betadeveloper pointed out that I can use the keyof typeof Locales type for my approach. The solution I eventually came up with looks like this:

const keys: (keyof typeof Locales)[] = <(keyof typeof Locales)[]>Object.keys(Locales);
for (const key of keys) {
  const locale: string = Locales[key];
  console.log(locale); // Prints 'en', 'fr' and so on
}

Upvotes: 11

artem
artem

Reputation: 51649

As betadeveloper suggested, you can get proper type for key if you use type assertion as keyof typeof Locales. Or you can wrap it in type-safe variant of Object.keys() function like this:

export enum Locales {
  En = 'en',
  Fr = 'fr',
  De = 'de',
  Es = 'es',
  It = 'it',
  Nl = 'nl',
  No = 'no',
  Tr = 'tr',
}

function enumKeys<E>(e: E): (keyof E)[] {
  return Object.keys(e) as (keyof E)[];
}

for (const key of enumKeys(Locales)) {
  const locale: string = Locales[key];
  console.log(locale); 
}

Also, for the record, old-style for .. in loop still works:

for (let key in Locales) {
    let locale = Locales[key];
    console.log(locale);
}

Upvotes: 15

Related Questions