A TypeScript custom transformer which strips const enum's code if preserveConstEnum is enabled and if a enum isn't exported from source file or entry points.
-
If you have enabled
preserveConstEnumcompiler option and want to strip non-exported from its source fileconst enums. -
Let's say you develop a library written in TypeScript and you use
const enums. Some of thatconst enums might be exported from the public API.Some of your users might "compile" their code with
transpileModule(e.g. bybabel-loader,ts-loaderwithtranspileOnlyenabled or directly by callingtranspileModulefromtypescript). To be sure that their code will be transpiled in this mode correctly, they very probably enableisolatedModulescompiler option.If so, that automatically means that they just can't use
const enums, exported from your library, because they will get an errorTS2748: Cannot access ambient const enums when the '--isolatedModules' flag is provided.That error means, that after transpiling the code will not contain a code for enums in JS output, so you'll get
ReferenceErrorin run-time.So, you have several options there:
- Don't use enums (all of them) at all 🙂
- Replace all
const enums with justenums. This means that you'll lose all advantages ofconst enums like inlining a values. - Enable
preserveConstEnumcompiler option to generate JS code forconst enums even if they will be inlined. But in this case you'll still have aconst enums in yourd.tsfiles. See microsoft/TypeScript#37774. For instance, indts-bundle-generatoryou can enablerespect-preserve-const-enumoption and the tool will stripconstfromconst enums in this case.
If you choose 3, you'll get all advantages internally (inlining
const enums) and don't break external code who uses transpilation over compilation.But here is another issue, this transformer is aim to fix - the TypeScript will generate
enumcode even if it's not exported. Moreover, no one minifier (I tested with Google Closure Compiler with advanced optimizations, terser, uglify-es, uglify-js) doesn't remove them, because the function has side-effects:const enum Enum { First, }
goes to:
var Enum; (function (Enum) { Enum[Enum["First"] = 0] = "First"; })(Enum || (Enum = {}));
This is why this transformer is here - it removes
const enum's code, if they aren't exported from entry points andpreserveConstEnumis enabled.With this transformer you'll get just
;instead of the code above:;
If preserveConstEnum is enabled and the source code contains const enum,
the transformer checks whether it's exported or not from either its source file or if entry points aren't empty from entry points.
If it's - then do nothing (as well as when preserveConstEnum is enabled), otherwise - replace it with ;.
All your code will contain inlined values so you don't need to worry about having that "object" in JS.
- Install the package
npm i -D ts-transformer-strip-const-enums - Add transformer with one of possible ways
Default: []
An array of entry source files which will used to detect "global" exports.
If you leave it empty, then the tool will check only const enum's source file.
Basically it should be entry point(s) of the library/project or an empty array, if you want to strip non-exported from source code const enums.
Unfortunately, TypeScript itself does not currently provide any easy way to use custom transformers (see microsoft/TypeScript#14419). The followings are the example usage of the custom transformer.
// webpack.config.js
const stripConstEnumsTransformer = require('ts-transformer-strip-const-enums').default;
module.exports = {
// ...
module: {
rules: [
{
test: /\.ts$/,
loader: 'ts-loader', // or 'awesome-typescript-loader'
options: {
getCustomTransformers: program => ({
before: [
stripConstEnumsTransformer(program, { entrySourceFiles: ['./src/index.ts'] })
]
})
}
}
]
}
};// rollup.config.js
import typescript from 'rollup-plugin-typescript2';
import stripConstEnumsTransformer from 'ts-transformer-strip-const-enums';
export default {
// ...
plugins: [
typescript({ transformers: [service => ({
before: [ stripConstEnumsTransformer(service.getProgram(), { entrySourceFiles: ['./src/index.ts'] }) ],
after: []
})] })
]
};See ttypescript's README for how to use this with module bundlers such as webpack or Rollup.
tsconfig.json:
{
"compilerOptions": {
// ...
"plugins": [
{ "transform": "ts-transformer-strip-const-enums", "entrySourceFiles": ["./src/index.ts"] }
]
},
// ...
}