String enums that know where they belong.

Enumwaii keeps familiar string values while TypeScript tracks the declaration that owns them. Parse boundaries, get useful errors, and enforce the relationship in CI.

Get startedRead the API

Make enum mistakes loud.

Explore mistakes from ordinary application code: authored literals, role-to-permission policies, and same-text values crossing domains.

Make every accepted role traceable.

Without enumwaii
Raw ADMIN accepted
  1. type Role = "ADMIN" | "USER";
  2. function canDelete(role: Role) { … }
  3.  
  4. canDelete("ADMIN"Argument of type "ADMIN" is accepted as RoleThe union checks spelling, but cannot require this value to come from a shared declaration.); // compiles

String unions stop typos, but still accept raw members wherever a Role is expected. Reviewers cannot tell whether ADMIN came from the declaration or memory.

With enumwaii
Declaration required
  1. const roles = em(["ADMIN", "USER"]);
  2. const ROLE = roles.enum;
  3. type Role = typeof roles["~type"];
  4. function canDelete(role: Role) { … }
  5.  
  6. canDelete("ADMIN"Argument of type "ADMIN" is not assignable to Role. ts(2345)A raw look-alike cannot satisfy the declaration-owned Role type.);
  7. canDelete(ROLE.ADMIN); // ✓

Owned members travel through ordinary functions like strings, but callers must use ROLE.ADMIN. Every accepted value points back to its source of truth.

Business logic stays familiar while the compiler enforces where members come from.declare once pass owned members trust the call

Own it

Reject accidental raw strings.

Only declaration-owned members satisfy your application types.

Parse it

Handle every boundary.

parse, safeParse, and Standard Schema validate external input.

Enforce it

Prevent future mistakes.

Optional ESLint rules make suspicious patterns visible in review.

Tested across the stack.

Explore examples
Hosts & runtimes
Node.js®BunDenoCloudflare Workers®
Web & mobile apps
Next.jsTanStack StartSolidVue
Servers & workflows
HonoElysiaNestJSoRPCEffect
Persistence
Drizzle ORMPGliteMongoose

Third-party marks identify tested integrations and do not imply endorsement. Cloudflare Workers remains text-only under its published trademark rules. Vercel, the Vercel design, Next.js and related marks, designs and logos are trademarks or registered trademarks of Vercel, Inc. or its affiliates in the US and other countries. Node.js is a trademark of the OpenJS Foundation. Cloudflare and Cloudflare Workers are trademarks and/or registered trademarks of Cloudflare, Inc. Review the asset audit.

Works wherever schemas work.

Every enumwaii declaration implements Standard Schema v1, the shared TypeScript contract for validators and the tools that consume them. Compatible libraries accept the declaration directly—no wrapper and no adapter dependency.

Schemas and adaptersWhat is Standard Schema?
roles.tsStandard Schema v1
const roles = em(["ADMIN", "USER"]);

const role = roles.parse(input);
const result = roles.safeParse(input);

await roles["~standard"].validate(input);
// Standard Schema v1 — built in

Add enumwaii with the tools you already use.

The same package runs across Node.js, Bun, Deno, browsers, and Cloudflare Workers.

npm install enumwaii