Typescript Enum Map

How do I display a typescript enumeration? For example, with strings you can do this:

let arr = [ 'Hello', 'Goodbye' ];

arr.map(v => {
  if (v === 'Hello') {
    return ':)';
  } else if (v === 'Goodbye') {
    return ':(';
  }
); // [ ':)', ':(' ]

This, of course, does not work with enumerations:

enum MyEnum { Hello, Goodbye };

MyEnum.map(v => {
  if (v === MyEnum.Hello) {
    return ':)';
  } else if (v === MyEnum.Goodbye) {
    return ':(';
  }
}); // does not work

Ideally, I would like to do this in a generalized way, so that I can just take any enumeration I have and pass it through the map function while saving the type information . Usage may look something like this:

map(MyEnum, v => {
  if (v === MyEnum.Hello) {
    return ':)';
  } else if (v === MyEnum.Goodbye) {
    return ':(';
  }
}); // [ ':)', ':(' ]

I deal with a function that does this for me, but I have problems getting generics all the time.

+9
source share
3 answers

The function to solve this problem is quite simple.

// you can't use "enum" as a type, so use this.
type EnumType = { [s: number]: string };

function mapEnum (enumerable: EnumType, fn: Function): any[] {
    // get all the members of the enum
    let enumMembers: any[] = Object.keys(enumerable).map(key => enumerable[key]);

    // we are only interested in the numeric identifiers as these represent the values
    let enumValues: number[] = enumMembers.filter(v => typeof v === "number");

    // now map through the enum values
    return enumValues.map(m => fn(m));
}

, (MyEnum.Hello 1 ), , .

( , ):

enum MyEnum { Hello, Goodbye };

let results = mapEnum(MyEnum, v => {
  if (v === MyEnum.Hello) {
    return ':)';
  } else if (v === MyEnum.Goodbye) {
    return ':(';
  }
});

console.log(results); // [ ':)', ':(' ]

, , - , .

:

var MyEnum;
(function (MyEnum) {
    MyEnum[MyEnum["Hello"] = 0] = "Hello";
    MyEnum[MyEnum["Goodbye"] = 1] = "Goodbye";
})(MyEnum || (MyEnum = {}));
;

"Hello" "Goodbye", .


type . , someParameter: enum, number -> string.

+4

ts-enum-util (npm, github) , ( ) :

import { $enum } from "ts-enum-util";

enum MyEnum { Hello, Goodbye };

$enum(MyEnum).map(v => {
    if (v === MyEnum.Hello) {
        return ':)';
    } else if (v === MyEnum.Goodbye) {
        return ':(';
    }
}); // produces [':(', ':)']

: ts-enum-util enum, . Object.keys() , " , " - . (: ts-enum-util , enum)

, ts-string-visitor (npm, github) , , , : (: ts-enum-util ts-string-visitor, !)

import { $enum } from "ts-enum-util";
import { mapString } from "ts-string-visitor";

enum MyEnum { Hello = "HELLO", Goodbye = "GOODBYE" };

$enum(MyEnum).map(v => {
    // compiler error if you forget to handle a value, or if you
    // refactor the enum to have different values, etc.
    return mapString(v).with({
        [MyEnum.Hello]: ':)',
        [MyEnum.Goodby]: ':('
    });
}); // produces [':(', ':)']
+1

, , :

type TMyEnum = ':)'|':(';
class MyEnum {
    static Hello: TMyEnum = ':)';
    static Goodbye: TMyEnum = ':(';
}
console.log(MyEnum.Hello); // :)
console.log(MyEnum.Goodbye); // :(

Now you do not need any matching function, and it works as expected, but you need to create a separate similar class for each enumeration (which should not be a problem, since you will do it anyway). The only drawback I can think of right now is that you cannot iterate over its properties. But so far this is not a problem for me, I do not need it. And you can add a static array to the class when you need it.

0
source

Source: https://habr.com/ru/post/1664723/


All Articles