https://github.com/eye-wave/better-enums
vite plugin that rewrites ts enums into tree-shakeable named const exports
https://github.com/eye-wave/better-enums
Last synced: 3 days ago
JSON representation
vite plugin that rewrites ts enums into tree-shakeable named const exports
- Host: GitHub
- URL: https://github.com/eye-wave/better-enums
- Owner: eye-wave
- Created: 2026-05-30T08:31:15.000Z (4 days ago)
- Default Branch: main
- Last Pushed: 2026-05-30T09:01:46.000Z (4 days ago)
- Last Synced: 2026-05-30T10:17:12.336Z (4 days ago)
- Language: JavaScript
- Size: 14.6 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# vite-plugin-better-enums
TypeScript enums are [famously problematic](https://www.typescriptlang.org/docs/handbook/enums.html) - they compile to IIFEs, they block tree-shaking.
This plugin rewrites `export enum` declarations at build time into plain named `const` exports in a virtual module, giving you all the ergonomics of enums with none of the baggage.
```js
// ------------
// Before
// ------------
//#region src/enum.ts
var Fruit = /* @__PURE__ */ (function (Fruit) {
Fruit[(Fruit["Apple"] = 0)] = "Apple";
Fruit[(Fruit["Banana"] = 1)] = "Banana";
Fruit[(Fruit["Kiwi"] = 2)] = "Kiwi";
return Fruit;
})({});
//#endregion
//#region src/main.ts
var a = Fruit.Apple;
console.log(a);
console.log(Fruit.Banana);
//#endregion
// ------------
// After
// ------------
var a = 1;
console.log(a);
console.log(2);
```
Usage stays exactly the same (except the indexing starts from 1 not 0):
```ts
import { Fruit } from "./fruit";
const pick: Fruit = Fruit.Apple; // 1
```
---
## How it works?
```ts
// ------------
// input
// ------------
export enum Fruit {
Apple,
Banana,
Kiwi,
}
// ------------
// output generated by the plugin
// ------------
export * as Fruit from "\0enum:/abs/path/fruit.ts?Fruit";
export type Fruit = 1 | 2 | 3;
// ------------
// generated Virtual Module
// ------------
export const Apple = 1;
export const Banana = 2;
export const Kiwi = 3;
```
---
## Why
| | TypeScript enum | This plugin |
| ---------------------------- | --------------- | ----------- |
| Tree-shakeable | ✗ | ✓ |
| Works with `isolatedModules` | ✗ | ✓ |
| Serializes cleanly to JSON | ✗ | ✓ |
| Familiar import syntax | ✓ | ✓ |
| Type-safe | ✓ | ✓ |
---
## Installation
```sh
npm install -D git+https://github.com/eye-wave/better-enums.git
```
---
## Setup
```ts
// vite.config.ts
import { defineConfig } from "vite";
import betterEnums from "vite-plugin-better-enums";
export default defineConfig({
plugins: [betterEnums()],
});
```
The plugin runs with `enforce: "pre"` so it transforms your source before esbuild or any other plugin sees it.
---
## Usage
Write enums exactly as you normally would - just make sure they're exported:
```ts
// status.ts
export enum Status {
Pending,
Active,
Archived,
}
```
Import and use them identically to before:
```ts
import { Status } from "./status";
function canEdit(s: Status): boolean {
return s === Status.Active;
}
```
Multiple enums in one file work fine:
```ts
export enum Color {
Red,
Green,
Blue,
}
export enum Size {
Small,
Medium,
Large,
}
```
Non-exported enums are left completely untouched.
---
## Values
Members are assigned sequential integers in declaration order:
```ts
export enum Direction {
North, // 1
East, // 2
South, // 3
West, // 4
}
```
> **Note:** Initializers (`Foo = 5`) are unsupported right now and will throw a build error pointing to the offending member.
---
## Limitations & Caveats
Since this plugin transforms enums into plain objects at build time, there are a few architectural differences from standard TypeScript enums:
- **No Reverse Lookups:** You cannot do `Fruit[1]` to get the string `"Apple"`. Only forward lookups (`Fruit.Apple`) are supported.
- **Custom Initializers Unsupported:** Explicit values (like `Enum = 5` or `Enum = "value"`) are currently unsupported and will throw a build error. All enums are strictly auto-incremented starting from 1.
- **Ambient Enums:** `declare enum` statements are ignored.
---
## License
MIT