@devmuggs/enum
v0.0.1
Published
Better TypeScript enums
Readme
@devmuggs/enum
A tiny, type-safe, zero-dependency enum utility for TypeScript.
@devmuggs/enum gives you flat enum member access for the common case and a small $. namespace for runtime helpers.
Why
- Keeps enum members ergonomic:
Season.Winter - Preserves runtime data: keys, values, guards, reverse lookup, matching
- Preserves literal inference without TypeScript
enum - Keeps library-owned helpers off the main enum key space
- Ships as plain TypeScript with no dependencies
Quick Start
import $enum from "@devmuggs/enum";
const Season = $enum({
Spring: "spring",
Summer: "summer",
Fall: "fall",
Winter: "winter"
});
Season.Spring;
Season.Winter;
Season.$.values;
Season.$.isValue("spring");
const message = Season.$.match(Season.Spring, {
[Season.Spring]: () => "It's spring!",
[Season.Summer]: () => "It's summer!",
[Season.Fall]: () => "It's fall!",
[Season.Winter]: () => "It's winter!"
});API Shape
const Season = $enum({
Spring: "spring",
Summer: "summer",
Fall: "fall",
Winter: "winter"
});
Season.Spring;
Season.$.keys;
Season.$.values;
Season.$.reverseLookup.spring;
Season.$.isKey("Spring");
Season.$.isValue("spring");The returned object is frozen, and the $. object is frozen too.
Creating Enums
You can create an enum from an object:
const Status = $enum({
Active: "active",
Pending: "pending"
});
Status.Active;
Status.Pending;Or from a list of string values:
const DaysOfWeek = $enum(
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
"Sunday"
);
DaysOfWeek.Monday;
DaysOfWeek.Sunday;Guards
Use isKey and isValue when narrowing unknown input.
if (Season.$.isKey(input)) {
// input is "Spring" | "Summer" | "Fall" | "Winter"
}
if (Season.$.isValue(input)) {
// input is "spring" | "summer" | "fall" | "winter"
}Matching
match supports both exhaustive matching and partial matching with a required _ fallback.
Exhaustive match:
const label = Season.$.match(Season.Spring, {
[Season.Spring]: () => "It's spring!",
[Season.Summer]: () => "It's summer!",
[Season.Fall]: () => "It's fall!",
[Season.Winter]: () => "It's winter!"
});Match with default:
const label = Season.$.match(Season.Summer, {
[Season.Fall]: () => "It's fall!",
[Season.Winter]: () => "It's winter!",
_: () => "Unknown season"
});Derive
derive lets you build value-indexed lookup objects from an enum.
const SeasonSortOrder = Season.$.derive({
[Season.Spring]: 1,
[Season.Summer]: 2,
[Season.Fall]: 3,
[Season.Winter]: 4
});
SeasonSortOrder[Season.Spring];Pick And Omit
pick and omit return objects keyed by the original enum keys, with IntelliSense preserved.
const WarmSeasons = Season.$.pick(Season.Spring, Season.Summer);
// ^? { Spring: "spring"; Summer: "summer" }
const ColdSeasons = Season.$.omit(Season.Spring, Season.Summer);
// ^? { Fall: "fall"; Winter: "winter" }Type Helpers
The function and namespace share the same name, similar to z.infer in Zod.
const Season = $enum({
Spring: "spring",
Summer: "summer",
Fall: "fall",
Winter: "winter"
});
type SeasonValue = $enum.infer<typeof Season>;
type SeasonKeys = $enum.keys<typeof Season>;
type SeasonValues = $enum.values<typeof Season>;Notes
- The top-level enum object is optimized for member access like
Season.Winter. - Runtime helpers live under
$.to avoid polluting user-defined enum keys. pickrelies on enum values being unique because it uses reverse lookup to recover the original keys.
