Home > other >  How to get the size of a const enum in TypeScript?
How to get the size of a const enum in TypeScript?

Time:11-28

Let's say I have a constant enum like this:

const enum Fruit {
  Apple = 1,
  Banana,
  Carrot,
  Dragonfruit
}

The size of this enum would be 4. When it's not a const enum, one can simply call something like Object.keys and do some math to get the size of it. However, I do not believe that works with a const enum.

Another alternative that people recommend is to include SIZE parameter, like so:

const enum Fruit {
  Apple = 1,
  Banana,
  Carrot,
  Dragonfruit,
  __SIZE
}

And then query Fruit.__SIZE to get the size. However, this has two problems:

  1. This application is networked, so when I eventually add more fruit, another fruit will take the spot of __SIZE as it is bumped up. This could cause issues due to the new fruit having the same integer id as the previous SIZE / NULL slot.

  2. One has to always remember to keep the __SIZE value last, so it's prone to breakage due to a programmer forgetting to keep it synced.

Is there an alternative? Since it only has to be computed once when the application starts up, I don't even mind if it is very slow.

CodePudding user response:

The problem with const enums is that they are compiled away by the TS compiler (see relevant answer to another SO question). It sort of falls prey to the same limitations that interfaces (compiled away) have vs classes (retained as JS code) with regards to what is possible at runtime.

The benefit of a construct that is compiled away is that is doesn't leave a code overhead, but as a result can't be used to make any runtime determinations. In this case, as you need to be able to determine the length of the enum at runtime (as opposed to at compile time as with your __SIZE approach), you would benefit from dropping the const, accepting the code overhead, but having a resulting lookup object that can be evaluated.

TypeScript Playground - normal

Interestingly, there is a tsconfig option called preserveConstEnums that does exactly this also; prevents const enums being compiled away and generates the same lookup object that would be generated if enum had been used. However annoyingly this doesn't appear to bypass the warning, at least not on the TS playground, so doesn't appear to be a solution. Someone else may be able to shed some light on whether this option can be used in practice.

TypeScript Playground - with preserveConstEnums

CodePudding user response:

I have a tentative solution to this, which may work for some people (me at least).

I have a data mapping in my application, that looks something like this:

const dataFruit: Record<Fruit, FruitData> = {
  [Fruit.Apple]: { taste: "yum" },
  [Fruit.Banana]: { taste: "tasty" },
  [Fruit.Carrot]: { taste: "hmm" },
  [Fruit.Dragonfruit]: { taste: "okay" },
}

Because of the record's type, it enforces that every single Fruit enum entry is in the mapping. If you miss one, the program fails to compile (this is good).

As a result, we can now do this:

const mapSize = Object.keys(dataFruit).length;

To get the number of entries in the enum.

If you didn't require a data mapping, I suppose you could create a useless one in a function (where each value was the number zero), and then just use that to cache the enum length for run-time. This has the benefit of not using any run-time memory (the temporary object will be garbage-collected away after the function ends), you can still use const enums, and the solution prevents you from forgetting to update the size (due to compiler errors).

  • Related