Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the type of an enum in Typescript?

Given a function that has an argument supposed to be an enum. The enum passed in can have different numbers of properties. How to fix the type of that argument ? enum itself is not a type.

E.g. :

function (myEnum: mysteriousType){   //What is that mysteriousType ? } 


The use case is to build a generic method to instantiate dat.GUI options from an enum, whatever the string/number type in the enum.
like image 749
Mouloud88 Avatar asked May 03 '18 15:05

Mouloud88


People also ask

Is enum a type or value TypeScript?

Enums or enumerations are a new data type supported in TypeScript. Most object-oriented languages like Java and C# use enums. This is now available in TypeScript too. In simple words, enums allow us to declare a set of named constants i.e. a collection of related values that can be numeric or string values.

What is enum data type?

An enum type is a special data type that enables for a variable to be a set of predefined constants. The variable must be equal to one of the values that have been predefined for it. Common examples include compass directions (values of NORTH, SOUTH, EAST, and WEST) and the days of the week.

How do I find the enum type?

To get the value of enum we can simply typecast it to its type. In the first example, the default type is int so we have to typecast it to int. Also, we can get the string value of that enum by using the ToString() method as below.

What is enum type in JavaScript?

Enums or Enumerated types are special data types that set variables as a set of predefined constants. In other languages enumerated data types are provided to use in this application. Javascript does not have enum types directly in it, but we can implement similar types like enums through javascript.


1 Answers

With what you've stated so far (needs to accept all string / numeric / heterogeneous enums), the closest I can do is something like this:

type Enum<E> = Record<keyof E, number | string> & { [k: number]: string }; function acceptEnum<E extends Enum<E>>(   myEnum: E ): void {    // do something with myEnum... what's your use case anyway? }  enum E { X, Y, Z }; acceptEnum(E); // works 

I'm not sure what you're going to do with myEnum if all you know is that it's "some enum type", but I guess that's up to you to figure out.


How I came up with this: I examined a bunch of concrete enum types, and they seem to have properties with string keys and string or numeric values (the forward mapping), as well as a numeric index key with string values (the reverse mapping for numeric values).

const works: { X: 0, Y: 1, Z: 2, [k: number]: string } = E; // works 

The language designers might have constrained this further, since the reverse mapping will only produce the specific numeric keys and string values seen in the forward mapping, but for some reason it's not implemented like that:

const doesntWork: { X: 0, Y: 1, Z: 2, [k: number]: 'X' | 'Y' | 'Z' } = E; // error const alsoDoesntWork: { X: 0, Y: 1, Z: 2, 0: 'X', 1: 'Y', 2: 'Z' } = E; // error 

So the tightest constraint I can put on an enum type is the above E extends Enum<E>.


Note that this code does not work for const enum types which don't really exist at runtime:

const enum F {U, V, W}; acceptEnum(F); // nope, can't refer to `F` by itself 

And also note that the above type (E extends Enum<E>) allows some things it maybe shouldn't:

acceptEnum({ foo: 1 }); // works 

In the above, {foo: 1} is plausibly a numeric enum similar to enum Foo {foo = 1} but it doesn't have the reverse mapping, and if you rely on that things will blow up at runtime. Note that {foo: 1} doesn't seem to have an index signature but it still matches an index signature implicitly. It wouldn't fail to match unless you added some explicit bad value:

acceptEnum({foo: 1, 2: 3}); // error, prop '2' not compatible with index signature 

But there's nothing to be done here. As I mentioned above, the implementation of enum typing currently does not constrain the numeric keys as much as it can, so there seems to be no way at compile time to distinguish between an enum with a good reverse mapping and one without one.


Hope that helps. Good luck!

like image 140
jcalz Avatar answered Oct 17 '22 15:10

jcalz