microsoft / TypeScript

TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
https://www.typescriptlang.org
Apache License 2.0
101.07k stars 12.49k forks source link

[Feature] make generated codes from enum could be minified when not used #27604

Open morlay opened 6 years ago

morlay commented 6 years ago

Search Terms

For now TypeScript will transform enum from

enum Test {
    Key = 1
}

to

var Test;
(function (Test) {
    Test[Test["Key"] = 1] = "Key";
})(Test || (Test = {}));

This result is not friendly for uglyify or tree-shaking. When Test is not be used, the generated code block always remain as dead codes.

Suggestion

prefer to generate codes below:

var Test = /*#__PURE__*/(function () {
    var e = {}
    e[e["Key"] = 1] = "Key";
    return e
})();

Examples

image

The suggestion version will be removed.

Checklist

My suggestion meets these guidelines:

azizhk commented 5 years ago

Well I guess this is blocked because we need to be able to extend enums as well. The only way I can think of this is doing something like:

var ABC = /*@__PURE__*/(function (ABC) {
    ABC["A"] = "abc";
    ABC["B"] = "bcd";
    ABC["C"] = "cde";
    return ABC;
})(ABC || {});

ABC = /*@__PURE__*/(function (ABC) {
   ABC["D"] = "def";
   return ABC;
})(ABC || {});

for input:

enum ABC {
    A = "abc",
    B = "bcd",
    C = "cde"
}

enum ABC {
    D = "def"
}

Though terser will still not be able to remove both if we are extending the enum but atleast it would be able to remove it if we have only one declaration of the enum. Here the key point is that the var ABC and the ABC = need to be one statement.

Am here because my "tree-shakeability" tests just failed. 😅 (https://github.com/ritz078/pebble/pull/219) I would be happy to contribute if you can point me to the files where modifications need to be made.

morlay commented 5 years ago

@azizhk I have wrote a babel plugin https://github.com/morlay/babel-plugin-typescript-iife-enum to solve this. It is work fine in my projects.

azizhk commented 5 years ago

That's a neat trick @morlay, I actually use tsc to compile and then rollup (with babel) to bundle, I'll try if I can incorporate something similar in my setup.

morlay commented 5 years ago

@azizhk since babel support typescript. we could compile all through babel.

@azizhk since babel support typescript. we could compile all through babel.

my babel configuration bellow 
{
  "presets": [
    [
      "@babel/preset-env",
      {
        "targets": {
          "node": true
        }
      }
    ]
  ],
  "plugins": [
    "babel-plugin-typescript-iife-enum",
    "@babel/plugin-transform-typescript",
    "@babel/plugin-proposal-class-properties",
    "@babel/plugin-proposal-object-rest-spread",
    "babel-plugin-pure-calls-annotation"
  ]
}

babel-plugin-pure-calls-annotation is another helper to make uglify or terser happier. if all your named function is pure.

slavafomin commented 4 years ago

This is indeed a very needed feature. We have a lot of packages and we are using enums extensively. Right now, all enums from all packages are getting added to the final application bundle, even if we are not using them at all, or using only a very small subset of all possible values.

I guess, one workaround would be to use constant enums instead, if possible.

yordis commented 3 years ago

Hey folks, any updates on this one?

We are changing most of the types to be union types because of tree-shaking issues, would appreciate some support on the topic.