TypeScript enum to object array
Asked Answered
S

31

262

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?

Shroudlaid answered 29/3, 2017 at 17:53 Comment(2)
Enums are real objects that exist at runtime. So you are able to reverse the mapping doing something like this: GoalProgressMeasurements[GoalProgressMeasurements.Completed_Tasks] to get the enum name. I do not know if that helps.Zoophyte
Can you give a better description to "from our API", maybe give an example of usageRomanism
T
171

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",
}
Tropo answered 30/7, 2019 at 7:20 Comment(5)
Keep in mind that this will yield duplicates. The string value and the numerical value for each element, that is a type (string | YourEnumType)[] which is not what you might want in each case.Mordecai
is it guaranteed that the first half will be the keys and the second half will be the values? any reference?Rosaleerosaleen
@zedd45 What exactly are you referring to? The link basically leads to the 846 pages standard document, so it is hard to understand which aspect exactly you think is wrong.Pension
I went ahead and removed my comment, as I no longer recall what it was supposed to address back from August of last year. I think perhaps there were some comments about the naming convention of EcmaScript itself, not directly related to TS Enums.Blameless
This is no longer the case in TypeScript v5Hemotherapy
B
98

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));
Balustrade answered 26/7, 2018 at 9:59 Comment(6)
mmm if enum MyEnum { Part1 = 0, Part2 = 1 } turns into { Part1: 0, Part2: 1, 0: 'Part1', 1: 'Part2' } then, why when you console.log(Object.values(MyEnum)) it just only prints 0,1?Rosenberg
@JuanJoséRamírez where do you see that? For me Object.values(MyEnum) evaluates to ["Part1", "Part2", 0, 1]Balustrade
I just printed console.log(Object.values(MyEnum)) in my component. I'm using angular, not sure if that's related. I'm not that experienced in TypeScriptRosenberg
could the behavior change through different TS versions?Rosenberg
I've been checking the docs typescriptlang.org/docs/handbook/release-notes/… and it seems string enums have a different behavior. They do not get a reverse mapping generated at all. In my code, I was using a string enum, not the string in this example.Rosenberg
This can fail with members like '1e5' = 1, but that's quite the edge case.Gambrinus
D
49

Simply this will return an array of enum values:

 Object.values(myEnum);
Defamatory answered 4/6, 2020 at 14:15 Comment(3)
Because it's doesn t give the right result, check https://mcmap.net/q/109067/-typescript-enum-to-object-arraySplotch
@walox, It is giving right result only, the link you gave is not showing correct values. Ideally object.keys will return array of keys and object.values will return array of values.Defamatory
This is enough if your enum consists of key-string pairs like enum xxx {create = "create"}Pridgen
Z
48

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

Zoophyte answered 29/3, 2017 at 18:19 Comment(3)
you do not need to write the defaults = 2 until = 5 - Anything after = 1 is +1 automatically.Paries
Maybe you don't need to, but it is more expressive. Which makes it better IMHO.Praedial
just a note this doesn't work for string value enumsNelle
H
35

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, ' ') }))
 }
Helsinki answered 4/2, 2018 at 16:31 Comment(2)
you should filter the keys of type number Object.keys(GoalProgressMeasurements) .filter(key => typeof GoalProgressMeasurements[key] === 'number') .map(key => ({ id: GoalProgressMeasurements[key], name: key }))Sheared
Works perfect for string based enums like: export enum UserRole { STUDENT = 'Estudiante', DIRECTOR = 'Director de carrera', AUTHORITY = 'Autoridad', FINANCIAL = 'Dirección Financiera' }Artimas
R
25

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.

Rudd answered 24/1, 2020 at 12:21 Comment(2)
Not compatible with IE with front-end (should not support ie is a great answer...but I guess customers). Hoping babel transpires it, but sticking to other approaches since I haven't verified itGumption
string enum is easy, just do Object.values(GoalProgressMeasurement)Rudd
R
18

Thanks to polkovnikov.ph I was finally able to find a solution that would work for most of the use-cases.

Valid solution for the question

type Descripted<T> = {
    [K in keyof T]: {
        readonly id: T[K];
        readonly description: string;
    }
}[keyof T]

/**
 * Helper to produce an array of enum descriptors.
 * @param enumeration Enumeration object.
 * @param separatorRegex Regex that would catch the separator in your enum key.
 */
export function enumToDescriptedArray<T>(enumeration: T, separatorRegex: RegExp = /_/g): Descripted<T>[] {
    return (Object.keys(enumeration) as Array<keyof T>)
        .filter(key => isNaN(Number(key)))
        .filter(key => typeof enumeration[key] === "number" || typeof enumeration[key] === "string")
        .map(key => ({
            id: enumeration[key],
            description: String(key).replace(separatorRegex, ' '),
        }));
}

Example:


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

console.log(enumToDescriptedArray(GoalProgressMeasurements))
// Produces:
/*
[
    {id: 1, description: "Percentage"},
    {id: 2, description: "Numeric Target"},
    {id: 3, description: "Completed Tasks"},
    {id: 4, description: "Average Milestone Progress"},
    {id: 5, description: "Not Measured"}
]
*/

Also, there's a useful util function I use to map the enumeration object to an array of available values it has:

The mapper

type NonFunctional<T> = T extends Function ? never : T;

/**
 * Helper to produce an array of enum values.
 * @param enumeration Enumeration object.
 */
export function enumToArray<T>(enumeration: T): NonFunctional<T[keyof T]>[] {
    return Object.keys(enumeration)
        .filter(key => isNaN(Number(key)))
        .map(key => enumeration[key])
        .filter(val => typeof val === "number" || typeof val === "string");
}

Working use-cases

  • Numeric enum
enum Colors1 {
    WHITE = 0,
    BLACK = 1
}
console.log(Object.values(Colors1)); // ['WHITE', 'BLACK', 0, 1]
console.log(enumToArray(Colors1));   // [0, 1]
  • String enum
enum Colors2 {
    WHITE = "white",
    BLACK = "black"
}
console.log(Object.values(Colors2)); // ['white', 'black']
console.log(enumToArray(Colors2));   // ['white', 'black']
  • Heterogenous enum
enum Colors4 {
    WHITE = "white",
    BLACK = 0
}
console.log(Object.values(Colors4)); // ["BLACK", "white", 0]
console.log(enumToArray(Colors4));   // ["white", 0]
  • Enum merged with a namespace with exported functions

enum Colors3 {
    WHITE = "white",
    BLACK = "black"
}
namespace Colors3 {
    export function fun() {}
}
console.log(Object.values(Colors3)); // ['white', 'black', Function]
console.log(enumToArray(Colors3));   // ['white', 'black']
Righthand answered 14/12, 2020 at 7:54 Comment(4)
Object.values returns properties in same order as for..in loop, and for..in returns them in arbitrary order. This code can return some arbitrary set of keys and values, depending on platform.Wetzel
@Wetzel You right, thanks! Now the new implementation is not relying on the order of Object.valuesRighthand
If it has numeric values, it can also be a heterogenous enum (see documentation), and this implementation will lose string values. Also it still doesn't answer original question.Wetzel
Thanks, I tried to improve the answer and added the exact solution for the question.Righthand
U
17
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]);
    }
}
Underlayer answered 21/4, 2019 at 9:28 Comment(3)
Thank you for these helpers. Very useful.Abdomen
Thanks for this. Saved me hours of messing around. Really useful a reusableFaulk
Fail! Not all enums have integers for values.Hargreaves
H
12

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.

Hoggard answered 6/1, 2020 at 15:16 Comment(1)
Result tested with TS4.6, objs: [ { id: 1, name: 'Rover' }, { id: 'Collie', name: 'Lassie' }, { id: 3, name: 'Fido' }, { id: 'Mutt', name: 'Cody' } ], entries: [ [ 'Rover', 1 ], [ 'Lassie', 'Collie' ], [ 'Fido', 3 ], [ 'Cody', 'Mutt' ] ], keys: [ 'Rover', 'Lassie', 'Fido', 'Cody' ] , values: [ 1, 'Collie', 3, 'Mutt' ]Jemappes
C
12

Example to get enum value inside array :

export enum DocumentationTypeEnum {
  GDPR = 'GDPR',
  HELP = 'HELP',
  OTHER = 'OTHER',
  FOOTER = 'FOOTER'
}
const keys = Object.keys(DocumentationTypeEnum);
    
console.log(keys); // Output :  ["GDPR", "HELP", "OTHER", "FOOTER"]
Corny answered 21/5, 2021 at 9:14 Comment(1)
How would I get this into a valid type? So instead of Array<string> get an Array type that can only hold the key values of the enum.Klinges
G
9

Just one line:

Object.entries(GoalProgressMeasurements).map(([key, value]) => ({id: key, value: value}))
Gainly answered 5/1, 2022 at 6:31 Comment(3)
fails for this typescriptlang.org/play?#code/… enum LAST_NUMBER_OF_TIME { LAST_60_DAYS = 60, LAST_30_DAYS = 30, LAST_15_DAYS = 15, LAST_1_WEEK = 7, LAST_1_DAY = 1, } Object.entries(LAST_NUMBER_OF_TIME).map(([key, value]) => ({id: key, value: value}))Ulland
@hafizali what is the error?Gainly
You will get array of array with combination of keys and values, that is the number of items for array of size 3 will be in total 6Ulland
I
4

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,
        };
    });
Indevout answered 22/1, 2020 at 8:28 Comment(3)
Welcome to stackoverflow. When answering questions, its a good idea to explain what your code snippet does. For more info, see here: How to AnswerFloater
Here are a few tips on how to make your answer greatMaximo
Please consider adding some explanation or details to your answer. While it might answer the question, just adding a piece of code as an answer, doesn't per say help OP or future community members understand the issue or the proposed solution.Transduction
B
4

Yet another approach using ES8 Object.entries

export enum Weeks {  
    MONDAY = 1,  
    TUESDAY= 2,  
    WEDNESDAY = 3,  
    THURSDAY = 4,  
    FRIDAY = 5,  
    SATURDAY=6,  
    SUNDAY=7,  
}


function convertEnumToArray(){
   const arrayObjects = []            
     // Retrieve key and values using Object.entries() method. 
     for (const [propertyKey, propertyValue] of Object.entries(Weeks)) { 

      // Ignore keys that are not numbers
      if (!Number.isNaN(Number(propertyKey))) {  
        continue;  
      }  

      // Add keys and values to array
      arrayObjects.push({ id: propertyValue, name: propertyKey });  
    }        

  console.log(arrayObjects); 
}

Will produce the following:

[ 
  { id: 1, name: 'MONDAY' },  
  { id: 2, name: 'TUESDAY' },  
  { id: 3, name: 'WEDNESDAY' },  
  { id: 4, name: 'THURSDAY' },  
  { id: 5, name: 'FRIDAY' },  
  { id: 6, name: 'SATURDAY' },  
  { id: 7, name: 'SUNDAY' } 
] 

Shamelessly stolen from this blog

Berkeleianism answered 16/6, 2021 at 12:49 Comment(0)
U
3

I would like to discourage using TS Enums in cases where list of enum entries is required.

In runtime Enum is implemented as object, but it works as you expect only in this case:

enum X {
  Z = 'z',
  F = 'f'
};

console.log(Object.values(X))
console.log(Object.keys(X))
>>>
[LOG]: ["z", "f"] 
[LOG]: ["Z", "F"] 

In this case it works with a trap (TS lets you to access value by it's numeric value):

enum X {
  Z,
  F
};

console.log(Object.values(X))
console.log(Object.keys(X))
>>>
[LOG]: ["Z", "F", 0, 1] 
[LOG]: ["0", "1", "Z", "F"] 

So any function you write to loop over Enum will work/fail according to Enum definition. Which is ... not good.

My conclusion: Enum was not designed to be used as an object. Use const instead of enum in case you need to access keys and values collections:

const Enumed = {
    X: 1,
    Y: 2
}

Typescript will control existence of object keys and you will be able to do Object.keys, etc. in safe and consistent way.

Unscrew answered 27/4, 2022 at 12:24 Comment(0)
H
3
export function enumKeys(E: any): string[] {
    return Object.keys(E).filter(k => isNaN(Number(k)));
}

export function enumValues(E: any): string[] | number[] {
    return enumKeys(E).map(k => E[k as any]);
}

Works with both:

enum TestA {
    RED = "red",
    BLUE = "blue"
}

enum TestB {
    ONE = 1,
    TWO = 2
}
Hargreaves answered 3/10, 2022 at 19:5 Comment(0)
T
3

I have solved it, this way. Suppose you have an enum like below

export enum UnitEnum {
  GRAM = 'gm',
  KILOGRAM = 'kg',
  LITRE = 'lt',
  CENTIMETER = 'cm',
  INCH = 'in',
  METER = 'mt',
  KILOMETER = 'km',
}

and, you have a class like this,

export interface Unit {
  Name: string;
  Symbol: string;
}

then you can create a function like below to map heterogenous enums to an object of certain type,

export function getDefaultUnits() {
  const myUnits = Object.entries(UnitEnum).map(x => {
    return { Name: x[0], Symbol: x[1] } as Unit
  })

  console.log(myUnits);

  return myUnits;
}
Tweeddale answered 22/1, 2023 at 16:41 Comment(0)
C
2

enum GoalProgressMeasurements {
    Percentage = 1,
    Numeric_Target = 2,
    Completed_Tasks = 3,
    Average_Milestone_Progress = 4,
    Not_Measured = 5
}
    
const array = []
    
for (const [key, value] of Object.entries(GoalProgressMeasurements)) {
    if (!Number.isNaN(Number(key))) {
        continue;
    }

    array.push({ id: value, name: key.replace('_', '') });
}

console.log(array);
Cafard answered 12/12, 2019 at 16:4 Comment(1)
Please put your answer always in context instead of just pasting code. See here for more details.Convalescence
M
2

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));
Medicinal answered 1/11, 2020 at 19:43 Comment(2)
Curious why this was downvoted? I had the same idea. Would the worry be that TypeScript would change and no longer make enums the same way?Piscatory
Order of Object.keys is not guaranteed.Wetzel
A
2

The solution below worked for me. Hope it may help someone as well -

export enum ScheduleType {
  Basic = <any>'B',
  Consolidated = <any>'C',
}

scheduleTypes = Object.keys(ScheduleType)
.filter((k, i) => i % 2)
.map((key: any) => {
  return {
    systemValue: key,
    displayValue: ScheduleType[key],
  };
});

It gave the following result - [{displayValue: "Basic", systemValue: "B"}, {displayValue: "Consolidated", systemValue: "C"}]

Agon answered 2/9, 2021 at 11:58 Comment(0)
K
1
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]);
}
Kv answered 31/12, 2020 at 17:56 Comment(0)
U
1

Let the enum variable be :

 enum EnumName {
      A = 1,
      B = 2
    };

Then the list is :

const list = Object.keys(Enum)
.filter((value => isNaN(Number(value)) === false))
      .map(key => ({ id: key, value: Enum[key] }));

The value of list will be

list = [ 
{ id:1 , value: A },
{ id:2 , value: B },
];
Unreason answered 28/4, 2022 at 16:45 Comment(0)
W
1

I like @Hakeem P A's answer's approach but it can be simplified quite a bit.

export enum MediaTypes {
    IMAGE = 1,
    AUDIO = 2,
    VIDEO = 3
}

To convert to an array of objects for something like binding to a select element options in Angular:

types = Object.entries(MediaTypes).filter(([key, val]) => typeof val === 'number').map(([key, val]) => ({ id: val, code: key }));

And then some form markup would look like:

<select name="media-type" [(ngModel)]="media.typeID" required>
    <option [ngValue]="null">&ndash;SELECT MEDIA TYPE&ndash;</option>
    <option [ngValue]="type.id" *ngFor="let type of types">{{type.code}}</option>
</select>
Waiver answered 15/7, 2023 at 4:8 Comment(0)
P
0

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.

Preside answered 30/3, 2019 at 9:46 Comment(0)
P
0

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:

    //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]);
    }
Progressive answered 4/9, 2020 at 14:12 Comment(0)
P
0

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]
  );
}
Primrose answered 13/10, 2020 at 14:57 Comment(0)
B
0

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
}
Bathos answered 24/11, 2020 at 20:49 Comment(0)
C
0

TS:

works ONLY with short (<10 elements) enum

const keys = Object.keys(Enum).filter((el: string) => el.length > 1)
console.log(keys)
  1. Object.keys() will return an array with ['0', '1', '2', 'enumElement1', 'enumElement2', enumElement3']
  2. filter() takes every element and check its length (because of string) and excludes all numbers from resulting array
Coycoyle answered 4/6, 2021 at 9:4 Comment(1)
Or an enum with key with length 1 is a problem tooPediment
C
0

this method based on statement: key of enum can't be a numeric

export const isNumeric = (num?: Value | null): num is number => {
  if (num === undefined || num === null) {
    return false;
  } 
  
  const number = +num;

  if (number - number !== 0) {
    // Discard Infinity and NaN
    return false;
  }

  if (number === num) {
    return true;
  }

  if (typeof num === 'string') {
    return !(number === 0 && num.trim() === '');
  }
  return false;
};

enum En  {
  ewq1 = 1,
  we2 = 'ss',
  sad = 'sad',
}

type TEnum = {
    [id: string]: number | string;
}

export const getEnumValues = <T extends TEnum>(enumerable: T) =>
  Object.keys(enumerable)
    .filter((x) => !isNumeric(x))
    .map((key) => enumerable[key] as T[keyof T]) 

console.log(getEnumValues(En)) // [1, "ss", "sad"] 
Crissie answered 27/10, 2021 at 21:4 Comment(0)
E
0

another way is

export const GoalNames = {
    [GoalProgressMeasurements.Percentage] = 'Percentage',
    [GoalProgressMeasurements.Numeric_Target] = 'Numeric Target',
    [GoalProgressMeasurements.Completed_Tasks] = 'Completed Tasks',
    [GoalProgressMeasurements.Average_Milestone_Progress] = 'Average Milestone Progress',
    [GoalProgressMeasurements.Not_Measured] = 'Not Measured'
}

and you can call:

const name = GoalNames[goalEnumVal];
Estrous answered 23/11, 2021 at 1:9 Comment(0)
T
0

I solved this way

        const listKeys = Object.keys(TripStatus); //TripStatus is enum type
        const numOfItem = listKeys.length/2;
        for(let i=0; i<numOfItem; i++){
          this.listStatus.push({
            id: listKeys[i],
            name: listKeys[numOfItem+i]
          })
        }
Tadd answered 29/12, 2021 at 5:40 Comment(0)
H
0
 this worked for me :

    export enum FeedBackType {
    FEEDBACK1= 'FEEDBACK1',
    FEEDBACK2= 'FEEDBACK2',
    FEEDBACK3= 'FEEDBACK3',
    }

----------------------------------------------------------------- 
    export function getTypeFeedBackList() {
    let feedbackList: FeedBackType[] = [];
    Object.keys(FeedBackType).map((key) => {
    let strEnum = key as unknown as FeedBackType;
    feedbackList.push(strEnum);
    });
    return feedbackList;
    }
---------------------------------------------------------------- 
declare this :

    public feedbackList: FeedBackType[] = [];

and after call your function in  :

    ngOnInit(): void {
    this.feedbackList = getTypeFeedBackList();
    console.log(this.feedbackList); 
    }

Happy coding ;) 
Homoeo answered 12/10, 2022 at 10:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.