BetterEnum is a lightweight TypeScript utility class for defining extensible, object-oriented enums with behavior. It enables enum-like static fields that retain their identity, support reverse lookups by name, and allow for rich custom behavior through class instances.
- Enum-like static fields with rich instance behavior
- Reverse lookup from string name (
fromString
) - Forward serialization to string (
toString
) - Enumeration of defined values (
values
) - Fully type-safe and extensible
npm install better-enum
Or with Yarn:
yarn add better-enum
JavaScript/TypeScript enum
s are limited: they can't hold methods, complex data, or behavior. BetterEnum
allows you to define classes with static members that behave like enums and objects — think Java-style enums with methods and fields.
import BetterEnum, { RegisterEnum } from 'better-enum';
@RegisterEnum
class Status extends BetterEnum {
static LOADING = new Status(true);
static READY = new Status(false);
private isBlocked: boolean;
constructor(isBlocked: boolean) {
super();
this.isBlocked = isBlocked;
}
getIsBlocked() {
return this.isBlocked;
}
}
Status.LOADING.getIsBlocked(); // true
Status.READY.getIsBlocked(); // false
Status.values(); // [Status.LOADING, Status.READY]
Status.LOADING.toString(); // "LOADING"
Status.fromString("READY") === Status.READY; // true
@RegisterEnum
class RCMascot extends BetterEnum {
public static readonly SNAP = Object.freeze(new RCMascot({
name: 'Snap',
doMath: (a, b) => a + b,
}));
public static readonly CRACKLE = Object.freeze(new RCMascot({
name: 'Crackle',
doMath: (a, b) => a - b,
}));
public static readonly POP = Object.freeze(new RCMascot({
name: 'Pop',
doMath: (a, b) => a * b,
}));
private name: string;
private doMathImpl: (a: number, b: number) => number;
constructor(args: { name: string, doMath: (a: number, b: number) => number }) {
super();
this.name = args.name;
this.doMathImpl = args.doMath;
}
getName() {
return this.name;
}
doMath(a: number, b: number) {
return this.doMathImpl(a, b);
}
}
RCMascot.SNAP.getName(); // "Snap"
RCMascot.POP.doMath(2, 3); // 6
RCMascot.fromString("CRACKLE") === RCMascot.CRACKLE; // true
RCMascot.values(); // [SNAP, CRACKLE, POP]
Base class to extend when creating enum-like classes.
Returns all enum values defined as static members on the subclass.
Returns the instance matching the given string name. Returns undefined
if not found.
Returns the string name of the enum instance based on its static member name.
The package includes thorough test coverage using Node's native test
module and assert
.
Run tests:
node --test
To use the @RegisterEnum
decorator, ensure your tsconfig.json
includes:
{
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true
}
}
- Classes extending
BetterEnum
must use the@RegisterEnum
decorator for automatic registration. - Static fields must be declared before runtime use for registration to succeed.
- The
@RegisterEnum
decorator requires TypeScript withexperimentalDecorators: true
in yourtsconfig.json
.
Inspired by Java-style enums with an ergonomic TypeScript twist.