441

What is the proper way to loop through literals of an enum in TypeScript?

(I am currently using TypeScript 1.8.1.)

I've got the following enum:

export enum MotifIntervention {
    Intrusion,
    Identification,
    AbsenceTest,
    Autre
}

export class InterventionDetails implements OnInit
{
    constructor(private interService: InterventionService)
    {
        let i:number = 0;
        for (let motif in MotifIntervention) {
            console.log(motif);
        }
    }

The result displayed is a list

0
1
2
3
Intrusion,
Identification,
AbsenceTest,
Autre

I do want only four iterations in the loop as there are only four elements in the enum. I don't want to have 0 1 2 and 3 that seem to be index numbers of the enum.

2
  • 1
    checkout this enum-for package Commented Jun 3, 2020 at 16:33
  • If you're not locked into using enum, it looks like this answer gives a better alternative. Commented Feb 20 at 1:41

4 Answers 4

705

Two options:

for (let item in MotifIntervention) {
    if (isNaN(Number(item))) {
        console.log(item);
    }
}

Or

Object.keys(MotifIntervention).filter(key => !isNaN(Number(MotifIntervention[key])));

(code in playground)


Edit

String enums look different than regular ones, for example:

enum MyEnum {
    A = "a",
    B = "b",
    C = "c"
}

Compiles into:

var MyEnum;
(function (MyEnum) {
    MyEnum["A"] = "a";
    MyEnum["B"] = "b";
    MyEnum["C"] = "c";
})(MyEnum || (MyEnum = {}));

Which just gives you this object:

{
    A: "a",
    B: "b",
    C: "c"
}

You can get all the keys (["A", "B", "C"]) like this:

Object.keys(MyEnum);

And the values (["a", "b", "c"]):

Object.keys(MyEnum).map(key => MyEnum[key])

Or using Object.values():

Object.values(MyEnum)
Sign up to request clarification or add additional context in comments.

11 Comments

Thanks for this approach. For the Object.keys method, you'll want to use Object.keys(MotifIntervention).filter(key => isNaN(Number(key))).
This doesn’t work if you're expecting to loop through values of the enum type. So for (let item in MotifIntervention) { doThing(item) } will fail if typeof doThing function is (arg: MotifIntervention) => void. That's because the for..in loop will treat item as type string, not type MotifIntervention.
@NitzanTomer - that sounds like a good workaround at runtime, but i'm talking about compile time. When you attempt to call doThing(item) and doThing is of type (arg: MotifIntervention) => void, you'll get a compile time error "Argument of type 'string' is not assignable to parameter of type 'MotifIntervention'."
I also include (typeof enumType[key] !== "function") in the filter to ignore methods I may have added to the enum type.
this will not work for enum X { "012" = 1 }
|
3

Enum Keys

Here is a solution which works for both string and numeric enums:

function enumKeys<T extends object>(e: T) {
  const keys = Object.keys(e)
  const isStringEnum = isNaN(Number(keys[0]))
  return isStringEnum ? keys : keys.slice(keys.length / 2)
}

To use simply do as following:

enum En {
  A,
  B,
  C,
}

console.log(enumKeys(En)); // ["A", "B", "C"]

enum Es {
  A = "a",
  B = "b",
  C = "c",
}

console.log(enumKeys(Es)); // ["A", "B", "C"]

Here is TS playground


Enum values

Also, to get enum values one can use:

function enumValues<T extends object>(e: T) {
  const values = Object.values(e)
  const isNumEnum = e[e[values[0]]] === values[0]
  return isNumEnum ? values.slice(values.length / 2) : values
}

To use simply do as following:

enum En {
  A,
  B,
  C,
}

console.log(enumValues(En)); // [0, 1, 2]

enum Es {
  A = "a",
  B = "b",
  C = "c",
}

console.log(enumValues(Es)); // ["a", "b", "c"] 

Here is TS Playground

1 Comment

Very elegant solution.
1
export enum MotifIntervention {
    Intrusion,
    Identification,
    AbsenceTest,
    Autre
}

const values = Object.values(MotifIntervention)

values.forEach(val => {
    //  -------> here is the value
})

const keys = Object.keys(MotifIntervention)

keys.forEach(key => {
    //  -------> here is the key
})

for string keys:

export enum LOCAL_STORAGE_KEYS {
  AUTH = 'auth',
  PERMISSIONS = 'permissions'
}

const storageKeys = Object.values(LOCAL_STORAGE_KEYS)

storageKeys.forEach(val => {
    //  -------> here the val is type if LOCAL_STORAGE_KEYS 
})

Comments

0

You can also use Enum.enums.

example Enum:

const eventType = new Enum({
    value0: 0,
    value1: 1,
    value2: 2
});

loop through like this:

for (let enumValues of eventType.enums) {
    let key = enumValues.key;
    let value = enumValues.value;
}

You can then display any key or value.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.