Typescript const enum alternative

1.5k views Asked by At

More and more modern Typescript transpilers have moved toward a strategy of per-module transpilation, which significantly increases build speed, but eliminates the possibility for cross-module const enum usage, since transpilation of them requires type information.

I have a significant amount of const enums that when used without the inlining that const provides:

  1. End up being hundreds of KBs even after minification due to long property names
  2. Leak internal, backend property names that I don't want public

Right now I have these const enum definitions auto generated from backend native code. As a contrived example, you can imagine I work at Apple and have a great big const enum of every hardware device.

const enum HardwareType {
    Apple1 = 0,
    // ...
    iPhoneX = 412,
    // ...
    iPhoneUltraXD = 499, // Some theoretical unannounced iPhone
}

If I just change const enum HardwareType to enum HardwareType, in addition to bumping up my bundle size, I've now leaked the new "iPhone Ultra XD" to the public.

I see that something like Terser supports the --mangle-props option, but even that seems to be warned against in the official docs and also would mean creating a regex that covers every single HardwareType? Not to mention that's just my contrived example and I have dozens of these enums in reality with hundreds of values.

I'd really like to use the latest tech for application bundling, but is there really not a better option out there for compile time inlining of constant values?

1

There are 1 answers

0
Michael Sereniti On

const enum is not very secure in hiding original names. As you can see in that playground typescript compiler adds original names in comments:

// Input:
const enum Fruites {
    Apple = 1,
    Banana = 2
}

const x = Fruites.Apple
const y = Fruites.Banana

// Output:
"use strict";
const x = 1 /* Apple */;
const y = 2 /* Banana */;

If your a really wondering to use the latest tech for application bundling and want to hide some secret names from output files, try to use esbuild-loader or esbuild itself. It support define option that allows you to replace some secret naming with meaningless values in compilation time like that

define: {
  "secrets.hardwareType.iPhoneUltraXD": "499"
}

and safely use the defined value in source code

// Source code: 
if (deviceId === secrets.hardwareType.iPhoneUltraXD) {
// Bundled code:
if(deviceId===499){

define option could be initiated in webpack or esbuild config file with any computed values (even with required json files) so you have no limit in count of compile-time definitions.