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
preserveConstEnum
compiler option and want to strip non-exported from its source fileconst enum
s. -
Let's say you develop a library written in TypeScript and you use
const enum
s. Some of thatconst enum
s might be exported from the public API.Some of your users might "compile" their code with
transpileModule
(e.g. bybabel-loader
,ts-loader
withtranspileOnly
enabled or directly by callingtranspileModule
fromtypescript
). To be sure that their code will be transpiled in this mode correctly, they very probably enableisolatedModules
compiler option.If so, that automatically means that they just can't use
const enum
s, 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
ReferenceError
in run-time.So, you have several options there:
- Don't use enums (all of them) at all 🙂
- Replace all
const enum
s with justenum
s. This means that you'll lose all advantages ofconst enum
s like inlining a values. - Enable
preserveConstEnum
compiler option to generate JS code forconst enum
s even if they will be inlined. But in this case you'll still have aconst enum
s in yourd.ts
files. See microsoft/TypeScript#37774. For instance, indts-bundle-generator
you can enablerespect-preserve-const-enum
option and the tool will stripconst
fromconst enum
s in this case.
If you choose 3, you'll get all advantages internally (inlining
const enum
s) 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
enum
code 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 andpreserveConstEnum
is 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 enum
s.
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"] }
]
},
// ...
}