Listing all the possible values for an enum in Typescript

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 = {}));

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 = {}));

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'	
}

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])

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


Publication date: 28/01/2021