10

I'm trying to find a way to convert the name of an enum to a string. If I have the Response enum below, how can I convert or extract 'Response' to a string? One of my functions takes any enum as input and I need the name, not the type of enum to execute other code.

enum Response 
{
    No = 0,
    Yes = 1 
}
Qwertiy
  • 19,681
  • 15
  • 61
  • 128
jurgen w
  • 243
  • 1
  • 2
  • 14
  • 1
    Possible duplicate of [Cast int to enum strings in Typescript](https://stackoverflow.com/questions/42299257/cast-int-to-enum-strings-in-typescript) – adiga Apr 08 '19 at 17:21
  • Also: https://stackoverflow.com/questions/18111657/how-does-one-get-the-names-of-typescript-enum-entries – StriplingWarrior Apr 08 '19 at 17:22
  • 3
    @adiga I'm not interested in getting string values from the enum values. I'm trying to convert the actual name of the enum itself 'Response' in this example, as a string. – jurgen w Apr 08 '19 at 17:31

4 Answers4

17

No, you can't convert an enum name to a string as type information is stored only during compilation. You have to pass additional parameters, specifying what enum are you using.


But you can use square brackets to convert enum value to a string and back:

Fiddle

enum YesNo {
    No = 0,
    Yes = 1, 
}

console.log(YesNo[YesNo.Yes]);
console.log(YesNo[YesNo.No]);
console.log(YesNo["Yes"]);
console.log(YesNo["No"]);
console.log(YesNo[1]);
console.log(YesNo[0]);

This code compiles into:

var YesNo;
(function (YesNo) {
YesNo[YesNo["No"] = 0] = "No";
YesNo[YesNo["Yes"] = 1] = "Yes";
})(YesNo || (YesNo = {}));
console.log(YesNo[YesNo.Yes]);
console.log(YesNo[YesNo.No]);
console.log(YesNo["Yes"]);
console.log(YesNo["No"]);
console.log(YesNo[1]);
console.log(YesNo[0]);
Matthias Braun
  • 32,039
  • 22
  • 142
  • 171
Qwertiy
  • 19,681
  • 15
  • 61
  • 128
  • 2
    For anyone else curious, `YesNo[1]` isn't an index reference but the value reference. So if `enum YesNo {No = 0, Yes=8}` then `console.log(YesNo[8])` returns `Yes`. Furthermore, if the value isn't found, it returns `undefined`. And if multiple enums have the same value like `enum YesNo {No = 8, Yes=8}`.. it returns the last one defined in the enum so in this case it would return `Yes`. – wongz Oct 29 '21 at 21:00
2
Object.keys({ Response })[0]; // 'Response'
Tukkan
  • 1,574
  • 2
  • 18
  • 33
  • This is so clever and should be the accepted answer! – David Fariña Mar 08 '23 at 17:01
  • -1 : OK, neat trick, however ... If you're in a line of code where you have the type hardcoded (Response), then you don't need to convert it to a string. The challenge is to get the type name from the type *after* it's been passed into a function. This won't work: `foo=func(Response) ... func getName(obj) { return Object.keys({ obj })[0]` - and it won't work with `typeof Response` or similar syntax. Unless there is a better solution, it seems the typename must be passed in as a parameter, as so far it doesn't look like it can be inferred. – TonyG May 26 '23 at 23:02
  • @TonyG Getting the name of a passed enum is the same as getting the name of passed variable - you can't do this as you are passing the reference or value, unless you use the trick I posted above and pass it as a parameter. OP wanted the way of getting the enum name and this is the only way of doing this. – Tukkan May 29 '23 at 12:52
  • @Tukkan : I agree to an extent and tried to remove my downvote, but it's not letting me. This is simply not a full solution to the OP's challenge. It's a hint at one part of how the problem can be solved, not an answer that can be accepted for implementation. Please see my answer which is fully implements your great answer here. – TonyG May 29 '23 at 23:32
1

How about:

MyEnum[MyEnum.option1]
Edwin
  • 733
  • 8
  • 20
0

@Tukkan provided the right answer but it was too vague to use. Here is functional code that responds directly the OP.

enum Options {
    yes,
    no
}
type EnumType = Record<string, any>
function showEnumName(theEnum: EnumType) {
    const enumName = Object.keys(theEnum)[0] ?? ''
    console.log(enumName)
}
showEnumName({ Options })

Playground Link

Notes:

  1. The enum object is passed into the function, and the function derives the name from that object. Compare this to the inspirational response by Tukkan which requires that the process that gets the enum name must have the literal enum object - not a reference to it, which is what the OP and most of us needs.
  2. The index [0] isn't necessary. Corrected: This depends on tsconfig setting. I modified to avoid compile-time warning, which may or may not be good policy, but that's beyond the scope of this thread.
  3. Typing the object passed into the function is required to get this to work without compile-time errors. You can simply use (theEnum:any) but that would allow, um, anything in there. If you have a function that types the enum object as 'any' before passing it to this code, it's going to break. The object must be an enum. More rigorous typing is also beyond the scope of this thread.
  4. If you change the function to use syntax closer to what Tukkan suggested, here is what happens Playground :
function showEnumName(theEnum) {
    const enumName = Object.keys({ theEnum })
    console.log(enumName)
}
showEnumName({ Options })

The result is not "Options", it's "theEnum". That is, as Tukkan correctly noted, it's telling us the name of the variable that contains the data, which doesn't help inside the function when we want the name of the enum that was passed in.

If you like this Answer, please also upvote the answer by @Tukkan so that he gets points. This one would not have been possible without his. I cannot in good conscience take exclusive points when he provided the inspiration.

TonyG
  • 1,432
  • 12
  • 31