-
-
Save scinscinscin/50dea8ae6a23903c2deb7c8a58b86845 to your computer and use it in GitHub Desktop.
A utility for building runtime enums which can be validated using Zod
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { ZodEnum, z } from "zod"; | |
interface RuntimeEnumT<T extends Readonly<string[]>> { | |
// @ts-ignore | |
validator: ZodEnum<T>; | |
enums: { | |
[key in T[number]]: key; | |
}; | |
} | |
/** | |
* A utility for building runtime enums which can be validated using Zod | |
* Useful for storing enum strings in the database then using them in the frontend | |
* @param enums An array containing strings to be used for the enum **as const** | |
* @returns Object with enums and associated validator | |
* @example ```tsx | |
* export const publishedEnum = RuntimeEnum(["published", "draft", "under_review"] as const); | |
* console.log(publishedEnum.enums.draft); // Prints "draft" | |
* | |
* // parse throws an error if it does not match | |
* const validated = publishedEnum.validator.parse("testing"); | |
* console.log(validated); // type: "published" | "draft" | "under_review" | |
* ``` | |
*/ | |
export function RuntimeEnum<T extends Readonly<string[]>>(enums: T): RuntimeEnumT<T> { | |
// @ts-ignore | |
const validator = z.enum(enums); | |
const enumObject = {} as { [key in T[number]]: key }; | |
enums.forEach((enum_name) => { | |
enumObject[enum_name as T[number]] = enum_name; | |
}); | |
// @ts-ignore | |
return { validator, enums: enumObject }; | |
} | |
/** | |
* A utility type for extracting all possible values for a RuntimeEnum | |
* @example | |
* ```tsx | |
* export const statusEnum = RuntimeEnum(["published", "draft", "under_review"] as const); | |
* type StatusEnum = GetRuntimeEnumValues<typeof statusEnum>; | |
* = "published" | "draft" | "under_review"; | |
* ``` | |
*/ | |
export type GetRuntimeEnumValues<T> = T extends RuntimeEnumT<infer U> ? U[number] : never; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment