Skip to content

Instantly share code, notes, and snippets.

@treyhoover
Last active January 3, 2026 18:10
Show Gist options
  • Select an option

  • Save treyhoover/57c206da965b1ab5eb79369b4f4892cd to your computer and use it in GitHub Desktop.

Select an option

Save treyhoover/57c206da965b1ab5eb79369b4f4892cd to your computer and use it in GitHub Desktop.
Hook for automatically creating helpers to
import { useState, useMemo } from "react";
// Usage example (booleans)
const userActivity = useEnum([true, false]);
userActivity.status; // true
userActivity.toggle();
userActivity.setTrue();
userActivity.setFalse();
userActivity.reset();
// Usage example (strings)
const camera = useEnum(["closed", "open"]);
camera.setClosed();
console.log(camera.isClosed); // true
camera.setOpen();
console.log(camera.isOpen); // true
camera.setClosed();
camera.setOpen();
camera.toggle();
import { useState } from "react";
type Capitalize<S extends string> = S extends `${infer F}${infer R}` ? `${Uppercase<F>}${R}` : S;
type EnumActions<T extends readonly string[]> = {
[K in T[number] as `set${Capitalize<K>}`]: () => void;
};
type EnumCheckers<T extends readonly string[]> = {
[K in T[number] as `is${Capitalize<K>}`]: boolean;
};
type UseEnumResult<T extends readonly string[]> = {
value: T[number];
reset: () => void;
toggle: T["length"] extends 2 ? () => void : never;
} & EnumActions<T> &
EnumCheckers<T>;
function capitalize(s: string) {
return s.charAt(0).toUpperCase() + s.slice(1);
}
export function useEnum<const T extends readonly [string, ...string[]]>(values: T): UseEnumResult<T> {
const [value, setValue] = useState<T[number]>(values[0]);
const actions = Object.fromEntries(values.map((v) => [`set${capitalize(v)}`, () => setValue(v as T[number])]));
const checkers = Object.fromEntries(values.map((v) => [`is${capitalize(v)}`, value === v]));
const toggle = () => {
setValue((prev) => {
const idx = values.indexOf(prev);
return values[(idx + 1) % values.length] as T[number];
});
};
const reset = () => setValue(values[0]);
return { value, reset, toggle, ...actions, ...checkers } as UseEnumResult<T>;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment