[javascript] TypeScript enum to object array

I have an enum defined this way:

export enum GoalProgressMeasurements {
    Percentage = 1,
    Numeric_Target = 2,
    Completed_Tasks = 3,
    Average_Milestone_Progress = 4,
    Not_Measured = 5
}

However, I'd like it to be represented as an object array/list from our API like below:

[{id: 1, name: 'Percentage'}, 
 {id: 2, name: 'Numeric Target'},
 {id: 3, name: 'Completed Tasks'},
 {id: 4, name: 'Average Milestone Progress'},
 {id: 5, name: 'Not Measured'}]

Is there are easy and native way to do this or do I have to build a function that casts the enum to both an int and a string, and build the objects into an array?

This question is related to javascript arrays typescript enums casting

The answer is


A tricky bit is that TypeScript will 'double' map the enum in the emitted object, so it can be accessed both by key and value.

enum MyEnum {
    Part1 = 0,
    Part2 = 1
}

will be emitted as

{
   Part1: 0,
   Part2: 1,
   0: 'Part1',
   1: 'Part2'
}

So you should filter the object first before mapping. So @Diullei 's solution has the right answer. Here is my implementation:

// Helper
const StringIsNumber = value => isNaN(Number(value)) === false;

// Turn enum into array
function ToArray(enumme) {
    return Object.keys(enumme)
        .filter(StringIsNumber)
        .map(key => enumme[key]);
}

Use it like this:

export enum GoalProgressMeasurements {
    Percentage,
    Numeric_Target,
    Completed_Tasks,
    Average_Milestone_Progress,
    Not_Measured
}

console.log(ToArray(GoalProgressMeasurements));

If you are using ES8

For this case only it will work perfectly fine. It will give you value array of the given enum.

enum Colors {
  WHITE = 0,
  BLACK = 1,
  BLUE = 3
}

const colorValueArray = Object.values(Colors); //[ 'WHITE', 'BLACK', 'BLUE', 0, 1, 3 ]

You will get colorValueArray like this [ 'WHITE', 'BLACK', 'BLUE', 0, 1, 3 ]. All the keys will be in first half of the array and all the values in second half.

Even this kind of enum will work fine

enum Operation {
    READ,
    WRITE,
    EXECUTE
}

But this solution will not work for Heterogeneous enums like this

enum BooleanLikeHeterogeneousEnum {
  No = 0,
  Yes = "YES",
}

Enums are real objects that exist at runtime. So you are able to reverse the mapping doing something like this:

let value = GoalProgressMeasurements.Not_Measured;
console.log(GoalProgressMeasurements[value]);
// => Not_Measured

Based on that you can use the following code:

export enum GoalProgressMeasurements {
    Percentage = 1,
    Numeric_Target = 2,
    Completed_Tasks = 3,
    Average_Milestone_Progress = 4,
    Not_Measured = 5
}

let map: {id: number; name: string}[] = [];

for(var n in GoalProgressMeasurements) {
    if (typeof GoalProgressMeasurements[n] === 'number') {
        map.push({id: <any>GoalProgressMeasurements[n], name: n});
    }
}

console.log(map);

Reference: https://www.typescriptlang.org/docs/handbook/enums.html


Easy Solution. You can use the following function to convert your Enum to an array of objects.

 buildGoalProgressMeasurementsArray(): Object[] {

    return Object.keys(GoalProgressMeasurements)
              .map(key => ({ id: GoalProgressMeasurements[key], name: key }))
 }

If you needed to strip that underscore off, we could use regex as follows:

buildGoalProgressMeasurementsArray(): Object[] {

    return Object.keys(GoalProgressMeasurements)
              .map(key => ({ id: GoalProgressMeasurements[key], name: key.replace(/_/g, ' ') }))
 }

Simply this will return an array of enum values:

 Object.values(myEnum);

I use

Object.entries(GoalProgressMeasurement).filter(e => !isNaN(e[0]as any)).map(e => ({ name: e[1], id: e[0] }));

A simple 1 line that does the job.

It does the job in 3 simple steps
- Loads the combination of keys & values using Object.entries.
- Filters out the non numbers (since typescript generates the values for reverse lookup).
- Then we map it to the array object we like.


class EnumHelpers {

    static getNamesAndValues<T extends number>(e: any) {
        return EnumHelpers.getNames(e).map(n => ({ name: n, value: e[n] as T }));
    }

    static getNames(e: any) {
        return EnumHelpers.getObjValues(e).filter(v => typeof v === 'string') as string[];
    }

    static getValues<T extends number>(e: any) {
        return EnumHelpers.getObjValues(e).filter(v => typeof v === 'number') as T[];
    }

    static getSelectList<T extends number, U>(e: any, stringConverter: (arg: U) => string) {
        const selectList = new Map<T, string>();
        this.getValues(e).forEach(val => selectList.set(val as T, stringConverter(val as unknown as U)));
        return selectList;
    }

    static getSelectListAsArray<T extends number, U>(e: any, stringConverter: (arg: U) => string) {
        return Array.from(this.getSelectList(e, stringConverter), value => ({ value: value[0] as T, presentation: value[1] }));
    }

    private static getObjValues(e: any): (number | string)[] {
        return Object.keys(e).map(k => e[k]);
    }
}

I didn't like any of the above answers because none of them correctly handle the mixture of strings/numbers that can be values in TypeScript enums.

The following function follows the semantics of TypeScript enums to give a proper Map of keys to values. From there, getting an array of objects or just the keys or just the values is trivial.

/**
 * Converts the given enum to a map of the keys to the values.
 * @param enumeration The enum to convert to a map.
 */
function enumToMap(enumeration: any): Map<string, string | number> {
  const map = new Map<string, string | number>();
  for (let key in enumeration) {
      //TypeScript does not allow enum keys to be numeric
      if (!isNaN(Number(key))) continue;

      const val = enumeration[key] as string | number;

      //TypeScript does not allow enum value to be null or undefined
      if (val !== undefined && val !== null)
          map.set(key, val);
  }

  return map;
}

Example Usage:

enum Dog {
    Rover = 1,
    Lassie = "Collie",
    Fido = 3,
    Cody = "Mutt",
}

let map = enumToMap(Dog); //Map of keys to values

let objs = Array.from(map.entries()).map(m => ({id: m[1], name: m[0]})); //Objects as asked for in OP
let entries = Array.from(map.entries()); //Array of each entry
let keys = Array.from(map.keys()); //An array of keys
let values = Array.from(map.values()); //An array of values

I'll also point out that the OP is thinking of enums backwards. The "key" in the enum is technically on the left hand side and the value is on the right hand side. TypeScript allows you to repeat the values on the RHS as much as you'd like.


First we get an array of keys for this enum. Then, using the map () function, we convert the data to the desired format. id is obtained from the key, name is obtained from enum by the same key.

const converted = Object.keys(GoalProgressMeasurements).map(key => {
        return {
            id: GoalProgressMeasurements[key],
            name: key,
        };
    });

Here's the simple function with correct typing I use

/**
 * Helper to produce an array of enum values.
 * @param enumeration Enumeration object.
 */
export function enumToArray<T, G extends keyof T = keyof T>(enumeration: T): T[G][] {
  // tslint:disable: comment-format

  // enum Colors {
  //   WHITE = 0,
  //   BLACK = 1,
  // }
  // Object.values(Colors) will produce ['WHITE', 'BLACK', 0, 1]

  // So, simply slice the second half
  const enumValues = Object.values(enumeration);
  return enumValues.slice(enumValues.length / 2, enumValues.length) as T[G][];
}

Usage example:

enum Colors {
  Red = 1,
  Blue = 2,
}
enumToArray(Colors)

_x000D_
_x000D_
enum GoalProgressMeasurements {_x000D_
    Percentage = 1,_x000D_
    Numeric_Target = 2,_x000D_
    Completed_Tasks = 3,_x000D_
    Average_Milestone_Progress = 4,_x000D_
    Not_Measured = 5_x000D_
}_x000D_
    _x000D_
const array = []_x000D_
    _x000D_
for (const [key, value] of Object.entries(GoalProgressMeasurements)) {_x000D_
    if (!Number.isNaN(Number(key))) {_x000D_
        continue;_x000D_
    }_x000D_
_x000D_
    array.push({ id: value, name: key.replace('_', '') });_x000D_
}_x000D_
_x000D_
console.log(array);
_x000D_
_x000D_
_x000D_


There is a simple solution, So when you run Object.keys(Enum) that gonna give you a Array of Values and Keys, in first slice Values and in the second one keys, so why we don't just return the second slice, this code below works for me.

enum Enum {
   ONE,
   TWO,
   THREE,
   FOUR,
   FIVE,
   SIX,
   SEVEN
}
const keys = Object.keys(Enum); 
console.log(keys.slice(keys.length / 2));

Since enums with Strings values differ from the ones that have number values it is better to filter nonNumbers from @user8363 solution.

Here is how you can get values from enum either strings, numbers of mixed:

_x000D_
_x000D_
    //Helper
    export const StringIsNotNumber = value => isNaN(Number(value)) === true;
    
    // Turn enum into array
    export function enumToArray(enumme) {
      return Object.keys(enumme)
       .filter(StringIsNotNumber)
       .map(key => enumme[key]);
    }
_x000D_
_x000D_
_x000D_


You can do that in this way:

export enum GoalProgressMeasurements {
    Percentage = 1,
    Numeric_Target = 2,
    Completed_Tasks = 3,
    Average_Milestone_Progress = 4,
    Not_Measured = 5
}

export class GoalProgressMeasurement {
    constructor(public goalProgressMeasurement: GoalProgressMeasurements, public name: string) {
    }
}

export var goalProgressMeasurements: { [key: number]: GoalProgressMeasurement } = {
    1: new GoalProgressMeasurement(GoalProgressMeasurements.Percentage, "Percentage"),
    2: new GoalProgressMeasurement(GoalProgressMeasurements.Numeric_Target, "Numeric Target"),
    3: new GoalProgressMeasurement(GoalProgressMeasurements.Completed_Tasks, "Completed Tasks"),
    4: new GoalProgressMeasurement(GoalProgressMeasurements.Average_Milestone_Progress, "Average Milestone Progress"),
    5: new GoalProgressMeasurement(GoalProgressMeasurements.Not_Measured, "Not Measured"),
}

And you can use it like this:

var gpm: GoalProgressMeasurement = goalProgressMeasurements[GoalProgressMeasurements.Percentage];
var gpmName: string = gpm.name;

var myProgressId: number = 1; // the value can come out of drop down selected value or from back-end , so you can imagine the way of using
var gpm2: GoalProgressMeasurement = goalProgressMeasurements[myProgressId];
var gpmName: string = gpm.name;

You can extend the GoalProgressMeasurement with additional properties of the object as you need. I'm using this approach for every enumeration that should be an object containing more then a value.


I don't think the order can be guaranteed, otherwise it would be easy enough to slice the second half of Object.entries result and map from there.

The only (very minor) issues with the answers above is that

  • there is a lot of unnecessary type conversion between string and number.
  • the entries are iterated twice when a single iteration is just as clean and effective.
type StandardEnum = { [id: string]: number | string; [nu: number]: string;}

function enumToList<T extends StandardEnum> (enm: T) : { id: number; description: string }[] {
    return Object.entries(enm).reduce((accum, kv) => {
        if (typeof kv[1] === 'number') {
            accum.push({ id: kv[1], description: kv[0] })
        }
        return accum
    }, []) // if enum is huge, perhaps pre-allocate with new Array(entries.length / 2), however then push won't work, so tracking an index would also be required
}

function enumKeys(_enum) {
  const entries = Object.entries(_enum).filter(e => !isNaN(Number(e[0])));
  if (!entries.length) {
    // enum has string values so we can use Object.keys
    return Object.keys(_enum);
  }
  return entries.map(e => e[1]);
}

I'm surprised in a TypeScript thread no one gave valid TypeScript function with typing supported. Here's variation of @user8363 solution:

const isStringNumber = (value: string) => isNaN(Number(value)) === false;

function enumToArray<T extends {}>(givenEnum: T) {
  return (Object.keys(givenEnum).filter(isStringNumber) as (keyof T)[]).map(
    (key) => givenEnum[key]
  );
}

Questions with javascript tag:

need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax Drag and drop menuitems Is it possible to execute multiple _addItem calls asynchronously using Google Analytics? DevTools failed to load SourceMap: Could not load content for chrome-extension TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received type undefined raised when starting react app What does 'x packages are looking for funding' mean when running `npm install`? SyntaxError: Cannot use import statement outside a module SameSite warning Chrome 77 "Uncaught SyntaxError: Cannot use import statement outside a module" when importing ECMAScript 6 Why powershell does not run Angular commands? Typescript: No index signature with a parameter of type 'string' was found on type '{ "A": string; } Uncaught Invariant Violation: Too many re-renders. React limits the number of renders to prevent an infinite loop Push method in React Hooks (useState)? JS file gets a net::ERR_ABORTED 404 (Not Found) React Hooks useState() with Object useState set method not reflecting change immediately Can't perform a React state update on an unmounted component UnhandledPromiseRejectionWarning: This error originated either by throwing inside of an async function without a catch block Can I set state inside a useEffect hook internal/modules/cjs/loader.js:582 throw err How to post query parameters with Axios? How to use componentWillMount() in React Hooks? React Hook Warnings for async function in useEffect: useEffect function must return a cleanup function or nothing FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory in ionic 3 How can I force component to re-render with hooks in React? What is useState() in React? How to call loading function with React useEffect only once Objects are not valid as a React child. If you meant to render a collection of children, use an array instead How to reload current page? Center content vertically on Vuetify Getting all documents from one collection in Firestore ERROR Error: Uncaught (in promise), Cannot match any routes. URL Segment How can I add raw data body to an axios request? Sort Array of object by object field in Angular 6 Uncaught SyntaxError: Unexpected end of JSON input at JSON.parse (<anonymous>) Axios Delete request with body and headers? Enable CORS in fetch api Vue.js get selected option on @change Bootstrap 4 multiselect dropdown Cross-Origin Read Blocking (CORB) Angular 6: How to set response type as text while making http call

Questions with arrays tag:

PHP array value passes to next row Use NSInteger as array index How do I show a message in the foreach loop? Objects are not valid as a React child. If you meant to render a collection of children, use an array instead Iterating over arrays in Python 3 Best way to "push" into C# array Sort Array of object by object field in Angular 6 Checking for duplicate strings in JavaScript array what does numpy ndarray shape do? How to round a numpy array? How to update an "array of objects" with Firestore? How to increment a letter N times per iteration and store in an array? Cloning an array in Javascript/Typescript use Lodash to sort array of object by value TypeScript enum to object array How do I check whether an array contains a string in TypeScript? How to use forEach in vueJs? Program to find largest and second largest number in array How to plot an array in python? How to add and remove item from array in components in Vue 2 console.log(result) returns [object Object]. How do I get result.name? How to map an array of objects in React How to define Typescript Map of key value pair. where key is a number and value is an array of objects Removing object from array in Swift 3 How to group an array of objects by key Find object by its property in array of objects with AngularJS way Getting an object array from an Angular service push object into array How to get first and last element in an array in java? Add key value pair to all objects in array How to convert array into comma separated string in javascript Showing ValueError: shapes (1,3) and (1,3) not aligned: 3 (dim 1) != 1 (dim 0) Angular 2 declaring an array of objects How can I loop through enum values for display in radio buttons? How to convert JSON object to an Typescript array? Angular get object from array by Id Add property to an array of objects Declare an array in TypeScript ValueError: all the input arrays must have same number of dimensions How to convert an Object {} to an Array [] of key-value pairs in JavaScript Check if a value is in an array or not with Excel VBA TypeScript add Object to array with push Filter array to have unique values remove first element from array and return the array minus the first element merge two object arrays with Angular 2 and TypeScript? Creating an Array from a Range in VBA "error: assignment to expression with array type error" when I assign a struct field (C) How do I filter an array with TypeScript in Angular 2? How to generate range of numbers from 0 to n in ES2015 only? TypeError: Invalid dimensions for image data when plotting array with imshow()

Questions with typescript tag:

TS1086: An accessor cannot be declared in ambient context Element implicitly has an 'any' type because expression of type 'string' can't be used to index Angular @ViewChild() error: Expected 2 arguments, but got 1 Typescript: No index signature with a parameter of type 'string' was found on type '{ "A": string; } Understanding esModuleInterop in tsconfig file How can I solve the error 'TS2532: Object is possibly 'undefined'? Typescript: Type 'string | undefined' is not assignable to type 'string' Typescript: Type X is missing the following properties from type Y length, pop, push, concat, and 26 more. [2740] Can't perform a React state update on an unmounted component TypeScript and React - children type? ERROR in The Angular Compiler requires TypeScript >=3.1.1 and <3.2.0 but 3.2.1 was found instead What is "not assignable to parameter of type never" error in typescript? ERROR Error: Uncaught (in promise), Cannot match any routes. URL Segment How to convert string to boolean in typescript Angular 4 What is the Record type in typescript? Angular: How to download a file from HttpClient? Angular 6: saving data to local storage Sort Array of object by object field in Angular 6 How to use `@ts-ignore` for a block Setting values of input fields with Angular 6 Select default option value from typescript angular 6 Angular 6: How to set response type as text while making http call How to do a timer in Angular 5 Avoid "current URL string parser is deprecated" warning by setting useNewUrlParser to true Angular 5 Button Submit On Enter Key Press Importing json file in TypeScript Angular - "has no exported member 'Observable'" Property '...' has no initializer and is not definitely assigned in the constructor How to remove whitespace from a string in typescript? Angular 5 - Copy to clipboard Angular 5, HTML, boolean on checkbox is checked js 'types' can only be used in a .ts file - Visual Studio Code using @ts-check document.getElementById replacement in angular4 / typescript? Exclude property from type How to iterate using ngFor loop Map containing key as string and values as map iteration Read response headers from API response - Angular 5 + TypeScript 'mat-form-field' is not a known element - Angular 5 & Material2 Angular 5 Scroll to top on every Route click Angular File Upload Property 'value' does not exist on type 'Readonly<{}>' No provider for Http StaticInjectorError How to get query parameters from URL in Angular 5? Angular Material: mat-select not selecting default Angular (4, 5, 6, 7) - Simple example of slide in out animation on ngIf No provider for HttpClient I get "Http failure response for (unknown url): 0 Unknown Error" instead of actual error message in Angular Add items in array angular 4 Angular 4 checkbox change value How to import JSON File into a TypeScript file? How to generate components in a specific folder with Angular CLI?

Questions with enums tag:

Enums in Javascript with ES6 Check if value exists in enum in TypeScript Why Python 3.6.1 throws AttributeError: module 'enum' has no attribute 'IntFlag'? TypeScript enum to object array How can I loop through enum values for display in radio buttons? How to get all values from python enum class? Get enum values as List of String in Java 8 enum to string in modern C++11 / C++14 / C++17 and future C++20 Implementing Singleton with an Enum (in Java) Swift: Convert enum value to String? enum - getting value of enum on string conversion How to enumerate an enum with String type? How to get enum value by string or int Java enum with multiple value types C# Enum - How to Compare Value Pass in an enum as a method parameter Java Enum Methods - return opposite direction enum Why is enum class preferred over plain enum? How to get names of enum entries? What is the difference between `Enum.name()` and `Enum.toString()`? Getting String value from enum in Java Filling a List with all enum values in Java How to add extension methods to Enums C# how to use enum with switch Convert an enum to List<string> What is an idiomatic way of representing enums in Go? get enum name from enum value Casting string to enum Java Enum return Int Getting all names in an enum as a String[] Where is the documentation for the values() method of Enum? Java enum - why use toString instead of name List of enum values in java How to create enum like type in TypeScript? What is the reason for java.lang.IllegalArgumentException: No enum const class even though iterating through values() works just fine? Jackson enum Serializing and DeSerializer How to use enums in C++ How to Get enum item name from its value How to cast int to enum in C++? How can I output the value of an enum class in C++11 Java: using switch statement with enum under subclass What's the advantage of a Java enum versus a class with public static final fields? How to convert enum names to string in c What's the proper way to compare a String to an enum value? What's the use of "enum" in Java? Override valueof() and toString() in Java enum Working with Enums in android Is it possible to assign numeric value to an enum in Java? How to define an enum with string value? How to convert enum value to int?

Questions with casting tag:

Subtracting 1 day from a timestamp date Cast object to interface in TypeScript TypeScript enum to object array Casting a number to a string in TypeScript Hive cast string to date dd-MM-yyyy Casting int to bool in C/C++ Swift double to string No function matches the given name and argument types C convert floating point to int PostgreSQL : cast string to date DD/MM/YYYY Convert Int to String in Swift Convert Float to Int in Swift PostgreSQL: ERROR: operator does not exist: integer = character varying What is the difference between up-casting and down-casting with respect to class variable How to fix Warning Illegal string offset in PHP How to cast the size_t to double or int C++ How to have Java method return generic list of any type? Convert String to Date in MS Access Query What are the rules for casting pointers in C? C++ convert from 1 char to string? casting int to char using C++ style casting Convert Unicode data to int in python SELECT CONVERT(VARCHAR(10), GETDATE(), 110) what is the meaning of 110 here? Change column type in pandas Casting LinkedHashMap to Complex Object @Value annotation type casting to Integer from String Cast int to varchar How to avoid warning when introducing NAs by coercion Cast Object to Generic Type for returning Casting string to enum Java converting Image to BufferedImage Import pandas dataframe column as string not int TypeScript or JavaScript type casting Change type of varchar field to integer: "cannot be cast automatically to type integer" Convert base class to derived class SQL error "ORA-01722: invalid number" How to cast Object to its actual type? Why do we assign a parent reference to the child object in Java? CAST to DECIMAL in MySQL How to cast int to enum in C++? typecast string to integer - Postgres T-sql - determine if value is integer How do I concatenate a boolean to a string in Python? How to cast/convert pointer to reference in C++ Convert INT to FLOAT in SQL Cast Double to Integer in Java Why cannot cast Integer to String in java? Why don't Java's +=, -=, *=, /= compound assignment operators require casting? Android, How can I Convert String to Date? How do I convert a string to a number in PHP?