Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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+?

like image 397
kentor Avatar asked Dec 19 '17 23:12

kentor


3 Answers

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);
}
like image 89
artem Avatar answered Oct 29 '22 09:10

artem


@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
}
like image 36
kentor Avatar answered Oct 29 '22 08:10

kentor


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))
like image 38
Dany Gagnon Avatar answered Oct 29 '22 08:10

Dany Gagnon