swc-plugin-enum-to-obj
v0.3.0
Published
An SWC plugin to convert TypeScript enums into plain objects!
Downloads
7
Readme
swc-plugin-enum-to-obj
An SWC plugin to convert TypeScript enums into plain objects!
Installation
Install with your favorite package manager as devDependency.
npm i -D swc-plugin-enum-to-obj
Add plugin to wherever you have an SWC config (e.g. .swcrc
file, swc-loader
config, etc).
This plugin currently has no configuration. However you have to leave an empty object to meet SWC's API schema.
{
jsc: {
parser: {
syntax: 'typescript',
tsx: true,
},
experimental: {
plugins: [
['swc-plugin-enum-to-obj', {}],
],
}
},
}
Motivation
TypeScript enums are useful if they are used in suitable ways. However the compiled code of enums makes trouble. In order to support enum merging, TypeScript compiles them into IIFEs. I bet most of you won't use this feature, but it pollutes our compiled code.
// Before
export enum SimpleNumber {
Bar,
Baz,
}
// TypeScript compiles the above code to:
export var SimpleNumber;
(function(SimpleNumber) {
SimpleNumber[SimpleNumber["Bar"] = 0] = "Bar";
SimpleNumber[SimpleNumber["Baz"] = 1] = "Baz";
})(SimpleNumber || (SimpleNumber = {}));
This indeed works. But when you are trying to make a library containing enums, you will notice that enums are NOT tree-shakeable (e.g. rollup, SWC minify).
The compiled IIFE is a side-effect function call as the view of static code analysis. It cannot be safely removed because the analyzer don't have an idea about what it is doing.
Now that we know it is constructing enum objects, we can do this for it. This plugin picks up these compiled enum IIFEs and convert them to object literals.
After converting, bundlers and minifiers will be pleasure to remove all unused object literals for you. (e.g. rollup, SWC minify).
Why convert IIFEs instead of enums themselves? See this issue.
Examples
// Before
enum SimpleNumber {
Bar,
Baz,
}
// After
var SimpleNumber = {
"Bar": 0,
0: "Bar",
"Baz": 1,
1: "Baz"
};
// Before
export enum SimpleString {
A = 'Z',
B = 'Y',
}
// After
export var SimpleString = {
"A": 'Z',
"B": 'Y'
};
Caveats
Enum merging might not work.
This plugin strictly looks for the "
var X
+ IIFE" pattern. Mergings will be left unchanged.// Before enum Foo { Bar = 1 } enum Foo { Baz = 2 } // After var Foo = { "Bar": 1, 1: "Bar" }; (function(Foo) { Foo[Foo["Baz"] = 2] = "Baz"; })(Foo || (Foo = {}));
You might accidently convert enums of external libraries.
It is a problem caused by converting IIFEs.
If you are using libraries containing enums, and you make SWC process all node_modules file at the same time, those enums will be converted too because they also match the "
var X
+ IIFE" pattern.This should not cause any problems. However I think you should notice this behavior.
Enums containing complex caclucations are not supported.
This plugin strictly looks for number or string literals. However in some cases, SWC left calculation expressions stay in the IIFE. This kind of enums will be left unchanged.
// Before enum Foo { A = 3, B = 2, C = 1, X = A ** B ** C, } // After var Foo; (function(Foo) { Foo[Foo["A"] = 3] = "A"; Foo[Foo["B"] = 2] = "B"; Foo[Foo["C"] = 1] = "C"; Foo[Foo["X"] = Foo.A ** Foo.B ** Foo.C] = "X"; })(Foo || (Foo = {}));
const enum
s are handled by SWC, not this plugin.SWC currently converts
const enum
s the same way as normal enums. There will be an enum object as a result.
License
MIT