21

Similar to this question, but with the enumeration marked as a constant: How do you go about iterating or producing an array of from the const enum?

Example

declare const enum FanSpeed {
    Off = 0,
    Low,
    Medium,
    High
}

Desireable Results

type enumItem = {index: number, value: string};
let result: Array<enumItem> = [
    {index: 0, value: "Off"}, 
    {index: 1, value: "Low"}, 
    {index: 2, value: "Medium"}, 
    {index: 3, value: "High"}
];
Jim
  • 563
  • 1
  • 5
  • 19

2 Answers2

11

No, this is not possible with a const enum. Let's start with your original enum and log one of its values:

const enum FanSpeed {
    Off = 0,
    Low,
    Medium,
    High
}

console.log(FanSpeed.High);

The TypeScript compiler inlines all the references to FanSpeed, and compiles the above code into something like this:

console.log(3 /* High */);

In other words, since you're using a const enum, no FanSpeed object actually exists at run time, just simple numeric literals are passed around instead. With a regular, non-const enum, a FanSpeed would exist as a value and you could iterate over its keys.

Edit: If you can change the compiler settings of your project, see Titian's answer below for very useful information about the preserveConstEnums flag, which will cause a FanSpeed object to actually be created and thus give you a way to iterate over your enum.

JKillian
  • 18,061
  • 8
  • 41
  • 74
  • 2
    Is is possible to preserve the const enum using the preserveConstEnums compiler flag – Titian Cernicova-Dragomir Aug 29 '17 at 15:30
  • 1
    Yes, that's very important to mention @TitianCernicova-Dragomir. I linked to your answer from my answer so that they see what you wrote about `preserveConstEnums` – JKillian Aug 29 '17 at 15:35
  • I tried setting `"preserveConstEnums": true` in the tsconfig.json file for my project, but syntax highlighting still highlights an error when using either of the examples in the [referenced SO question](https://stackoverflow.com/questions/39372804/typescript-how-to-loop-through-enum-values-for-display-in-radio-buttons). I'm using Visual Studio Code and I'm not sure what other settings need to be applied. – Jim Aug 29 '17 at 15:40
  • 2
    @Jim as I mentioned in my answer with the preserveConstEnums the enum object is there but it is a bit tricky to access because the compiler insists it does not exist. – Titian Cernicova-Dragomir Aug 29 '17 at 15:49
  • @TitianCernicova-Dragomir, yeah, I'm digesting that now, in fact. My enum is placed in an `interfaces.d.ts` file along with many other interfaces and enums. Reading your post below and trying to decipher the right combination to reference that particular enum in the `for` loop. – Jim Aug 29 '17 at 15:53
  • d.ts files don't generate code, they are just used for definitions. You should move it to a .ts file – Titian Cernicova-Dragomir Aug 29 '17 at 15:54
7

You can use the preserveConstEnums compiler flag. This will emit the enum object in the Javascript but replace all values. The problem is that you can't for over the properties in a simple way because Typescript generates an error (enums can only be used in property or index access expressions or the right hand side of an import declaration or export assignment.). There are ways to get around it but it depends on your environment. Using modules you could write it like this:

import  * as e from "./enumModule"

for(var prop in (e as any)['FanSpeed']) {
  console.log(prop) ;
}

Or using a namespace you could do it like this:

namespace Enums { 
    export const enum FanSpeed {
        Off = 0,
        Low,
        Medium,
        High
    }
}
for(var prop in (Enums as any)['FanSpeed']) {
    console.log(prop) ;
}

Note: In either case you must use the preserveConstEnums compiler option first,

Titian Cernicova-Dragomir
  • 230,986
  • 31
  • 415
  • 357
  • Does the compiler flag need to be used on the module which defines the enums, or the module which consumes the enums, or both? What if the enums are imported from another project -- if not, might it work if you [re]export them from a module of your own? – ChrisW Dec 13 '18 at 13:46