4

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?

casieber
  • 7,264
  • 2
  • 20
  • 34
  • I understand the bundle size consideration but you're concern about "leaked" information is misplaced. For one thing `const enum` is for performance not security. For another, security through obscurity is unreliable and poor design. – Aluan Haddad Apr 16 '22 at 00:16
  • @AluanHaddad I don't believe this is security through obscurity. `const enum` actually removes the names during the compilation AFAIK, so unless you have access to the source code, there's no way you can know what does each number mean. – Silvino Escalona Apr 16 '22 at 01:21
  • I'm saying you shouldn't rely on information which is incidentally removed for other reasons, such as performance optimization, as a security feature. – Aluan Haddad Apr 16 '22 at 01:23
  • This is not a security issue. There is no security impact if Apple leaks the name of a new product. There is, however, a product/marketing/user impact of leaking. Additionally, my question is asking for alternatives that _don't_ rely on `const enum`, I'm not trying to defend it. If you have any useful ideas, I'm all ears. – casieber Apr 16 '22 at 17:14
  • If all your enums are global, you could theoretically use terser's conditional compilation api to define each enum member as a global... – Gerrit0 Apr 19 '22 at 16:25

1 Answers1

0

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.