Ivan Mushketyk
Ivan Mushketyk

Reputation: 8295

How to get the name of TypeScript enum type in runtime?

I would like to programmatically get the name of a TypeScript enum.

Say I have an enum like this:

enum MyEnum {
  v1 = 'v1',
  v2 = 'v2',
}

I would like to get the name of this enum programmatically. I tried the following:

const enumType = MyEnum
console.log(enumType.constructor.name) // I expect this to return "MyEnum"

But it displays "Object" instead.

Is there a way to get name of a TypeScript enum programmatically?

Upvotes: 7

Views: 5127

Answers (1)

VLAZ
VLAZ

Reputation: 29022

First off, the type system exists only at compile time. When you have

enum MyEnum {
  v1 = 'v1',
  v2 = 'v2',
}

Then TypeScript knows about the enums and ensures that doing MyEnum['v1'] is correct but raises a compile time problem for MyEnum['banana'].

Once the code is compiled, however, you have pure JavaScript. This is what gets executed at runtime.

Enums get compiled to plain JavaScript objects double binding the keys and values. That way, TS ensures the uniqueness of the enum values at runtime. The example enum given gets turned into:

var MyEnum;
(function (MyEnum) {
    MyEnum["v1"] = "v1";
    MyEnum["v2"] = "v2";
})(MyEnum || (MyEnum = {}));

See on TypeScript Playground

Once executed, you get a MyEnum variable that holds the plain object { v1: "v1", v2: "v2" }

I did say that TS will double-bind the keys and values. The example above doesn't demonstrate it well, so here is another one:

enum ExampleEnum {
  Apple = 1,
  Banana = 2,
}

will be turned into the plain object:

{ 
  1: "Apple", 
  2: "Banana", 
  Apple: 1, 
  Banana: 2 
}

See on TypeScript Playground

Thus both the keys (Apple and Banana) are unique, as would be the values (1 and 2), since they are all turned into keys of an object and you cannot have duplicate keys. It also allows you to do MyEnum[MyEnum[key]] to fetch what key is.

I don't suggest having duplicate values in your enum. Technically possible but you likely shouldn't. You'd have problems if you do MyEnum[MyEnum[key]]

At any rate, TypeScript does not encode the enum name as part of the enum, so once you're at runtime, you just have a plain JavaScript variable to work with. And you cannot get the name of a variable in JavaScript. At best, you can do something like:

function printVariableName(input) {
  console.log("Name:", Object.keys(input)[0]);
  console.log("Value:", Object.values(input)[0]);
}

var myVariable = 42;

printVariableName({myVariable});

However, this is just cheating a bit - you're passing an object which contains { myVariable: 42 }. This only works if you already know what the variable is, so it's of little use if you want to get the name indirectly through a different variable:

function printVariableName(input) {
  console.log("Name:", Object.keys(input)[0]);
  console.log("Value:", Object.values(input)[0]);
}

var myVariable = 42;
var myOtherVariable = myVariable;

printVariableName({myOtherVariable});

So, when you're passing around enums, e.g. you have a function like:

function doSomethingWithEnum(someEnum: MyEnum | MyOtherEnum): void {
  //do something with the passed in `someEnum`
}

Then if you call doSomethingWithEnum(MyEnum) then inside the body of the function you cannot de-reference what the passed in variable was.

Upvotes: 11

Related Questions