simpler enums in typescript

Clay Shentrup
Extreme Programming
1 min readFeb 10

--

i often see typescript enums used as constraints for redux actions and the like. for example:

enum ActionTypes {
GO = 'GO',
STOP = 'STOP',
}

export const goAction = createAction(ActionTypes.GO, (resolve) => {
return (payload?: any) => resolve(payload);
});

function funcThatAcceptsAnAction(action: ActionTypes) {
...
}

it would be far more concise to just do this:

enum ActionTypes {
GO,
STOP,
}

but then the value of e.g. ActionTypes.GO is a number instead of a string, and that’s bad for action debugging.

here’s the solution.

// "library" code
type EnumKey<T> = keyof T;
type StringEnum<T> = { [K in EnumKey<T>]: K };

function createEnumProxy<T extends object>(enumObject: T): StringEnum<T> {
type MyEnumKey = EnumKey<T>;

return new Proxy(
{} as StringEnum<T>,
{
get: (target: StringEnum<T>, property: PropertyKey): MyEnumKey => {
return property as MyEnumKey;
}
}
);
}

// usage
enum ActionTypesNum {
GO,
STOP,
}

export ActionTypes = createStringEnum(ActionTypesEnum)
console.log(ActionTypes.GO) // outputs "GO"

// argument typing
type ActionType = keyof typeof ActionTypesEnum; // or keyof typeof ActionTypes

function funcThatAcceptsAnAction(action: ActionType) {
...
}

playground link.

--

--

Clay Shentrup
Extreme Programming

advocate of score voting and approval voting. software engineer.