An open API service indexing awesome lists of open source software.

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

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