Here’s an overview of all the ways I’ve found to iterate an enum in TypeScript. I was particularly looking for how to iterate over the value of an enum, but still have the strongly typed value, instead of the underlying (string) value. But I decided to make this post about all possible ways I know of.

Default

Take this enum:

enum Color {
    Red, Green
}

Now add this code to log the values:

for (const value in Color) {
    log(value);
}

function log(value: string) {
    console.log(`Value: ${value}`);
}

Note: I’m using a separate log function to show what type the value is. You’ll see why later

When we run this code, we see:

Value: 0
Value: 1
Value: Red
Value: Green

So that’s a special thing to note! The enum actually contains both the numerical and the string value. You can see this in the resulting Javascript code in the TypeScript Playground.

Number Values

If we only want the numbers, we can use this code to log:

function log(value: string) {
    if (isNaN(Number(value))) {
        return;
    }

    console.log(`Value: ${value}`);
}

Member Names

What if we want only the member names? Easy, we can specify the underlying values when we define our enum:

enum Color {
    Red = "RED",
    Green = "GREEN"
}

Using the same loop and console code, we now get this:

Value: Red
Value: Green

You could also leave the enum as it was (keeping both the underlying number and string values), and check the type when logging:

function log(value: string) {
    if (!isNaN(Number(value))) {
        return;
    }
    
    console.log(`Value: ${value}`);
}

String Values

You can loop over an enum and get the member names as well:

enum Color {
    Red,
    Green
}

for (const value in Object.keys(Color)) {
    if (typeof Color[value] !== "string") {
        continue;
    }

    log(Color[Number(value)]);
}

function log(value: string) {
    console.log(`Value: ${value}`);
}

If the enum is backed by string values, this won’t work because the “value” in our loop is a string instead of a number. You might want to use this code:

enum Color {
    Red = "RED",
    Green = "GREEN"
}

function log(value: string) {
    console.log(`Value: ${value}`);
}

for (const value in Color) {
    log(Color[value]); //  <----- Error
}

But this won’t work because “value” is a string to TypeScript, but the indexer of “Color” can only accept “Red” or “Green”. So we need a helper method to create a new type:

function enumKeys<O extends object, K extends keyof O = keyof O>(obj: O): K[] {
    return Object.keys(obj).filter(k => Number.isNaN(+k)) as K[];
}

We can now use this code:

function log(value: Color) {
    console.log(`Value: ${value}`);
}

for (const value of enumKeys(Color)) {
    log(Color[value]);
}

This gives us the following result:

Value: RED
Value: GREEN

Also, notice how our “log” function now can accept a strongly-typed “Color” instead of a “string.”

Conclusion

So that’s basically it. There is code to get all the underlying values, the member names, the string values, and the strongly-typed values.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

This site uses Akismet to reduce spam. Learn how your comment data is processed.