DEV Community

Andrea Cappuccio
Andrea Cappuccio

Posted on • Originally published at stackrant.com

Listing all the possible values for an enum in Typescript

Today I have spent quite a few hours trying to contribute a P.R. to a project I really like, and often use in my day-to-day work, the excellent class-validator.
The problem I was trying to solve consisted in listing the possible values for a given enum, in order to let class-validator print them in its enum-related error messages.

The main problem is that enums get transpiled di

When values are not specified, an incremental integer is assigned to each key, so the transpiled JS looks like the following:

// Before
enum Steak {
    Medium,
    Rare,
    WellDone
}

// After
var Steak;
(function (Steak) {
    Steak[Steak["Medium"] = 0] = "Medium";
    Steak[Steak["Rare"] = 1] = "Rare";
    Steak[Steak["WellDone"] = 2] = "WellDone";
})(Steak || (Steak = {}));
Enter fullscreen mode Exit fullscreen mode

When an inteer number is assigned as the value, it is simply assigned instead of the deafult incremental integer in the example before.

When a string value is assigned, though, the transpiled JS code looks a bit different:

// Before
enum Steak {
    Medium = "MEDIUM",
    Rare = "RARE",
    WellDone "WELL_DONE"
}

// After
var Steak;
(function (Steak) {
    Steak["Medium"] = "MEDIUM";
    Steak["Rare"] = "RARE";
    Steak["WellDone"] = "WELL_DONE";
})(Steak || (Steak = {}));
Enter fullscreen mode Exit fullscreen mode

These transpilation differences lead to obvious inconsistencies when attempting to retrieve an enum's list of possible values when using the common Object.values(), Object.keys() and Object.entries() methods. By fiddling with an heterogeneous enum like the following:

enum TestEnum {
    a = 'aA',
    b = 'bB',
    c = 1,
    d = 2,
    e = '01'    
}
Enter fullscreen mode Exit fullscreen mode

The following conclusions can be drawn:

  • Object.values() returns an array containing all the possible values for the given enum AND the keys for the properties which have integer numbers as values ([ 'c', 'd', 'aA', 'bB', 1, 2, '01' ])
  • Object.keys() returns an array containing all the enum's keys plus all of the integer values defined ([ '1', '2', 'a', 'b', 'c', 'd', 'e' ])
  • Object.entries() returns an array of [key, value] arrays, plus N [value, key] entries for N of the enum's properties which have integer numbers as values ([ [ '1', 'c' ], [ '2', 'd' ], [ 'a', 'aA' ], [ 'b', 'bB' ], [ 'c', 1 ], [ 'd', 2 ], [ 'e', '01' ] ])

So, finally, the solution I came up with is:

Object.entries(TestEnum).filter(entry => !parseInt(entry[0])).map(entry => entry[1])
Enter fullscreen mode Exit fullscreen mode

Which starts from Object.keys()'s results, filtering out all the redundant [value, key] entries.

Top comments (0)