diff --git a/src/utils/enum/enum-key.ts b/src/utils/enum/enum-key.ts new file mode 100644 index 0000000..a277951 --- /dev/null +++ b/src/utils/enum/enum-key.ts @@ -0,0 +1,39 @@ +import { isReadOnlyMap } from "@/utils/collections"; + +/** + * A type that represents the key of an enum type `T`. + * + * @template T - The enum type whose keys are being represented. + */ +export type EnumKey<T> = keyof T extends string ? keyof T : never; + +/** + * Retrieves an array of the string keys of the specified `enum` object. + * + * @template T - Type of the enum. + * + * @param e - The enum object to retrieve the keys for. + * + * @returns An array of the string keys of the specified `enum` object. + */ +export function enumKeys<T>(e: T): EnumKey<T>[] { + if (isReadOnlyMap<EnumKey<T>, unknown>(e)) { + return [...e.keys()]; + } + + return Object.getOwnPropertyNames(e).filter(key => isEnumKey(e, key)) as EnumKey<T>[]; +} + +/** + * Determines if the provided key is an enumeration key. + * + * @template T - Type of the enum. + * + * @param e - The enum object to check the key against. + * @param key - The key to be checked. + * + * @returns `true` if the key is an enumeration key; otherwise, `false`. + */ +function isEnumKey<T>(e: T, key: string): key is EnumKey<T> { + return typeof e[key] !== "function" && key !== String(+key); +} diff --git a/tests/unit/utils/enum/enum-key.spec.ts b/tests/unit/utils/enum/enum-key.spec.ts new file mode 100644 index 0000000..e1d0465 --- /dev/null +++ b/tests/unit/utils/enum/enum-key.spec.ts @@ -0,0 +1,38 @@ +import { Enum } from "@/utils/enum/enum"; +import { enumKeys } from "@/utils/enum/enum-key"; + +describe("enumKeys", () => { + test("returns the correct keys for number-based built-in enums", () => { + enum NumberEnum { + A = 1, + B = 2, + C = 3, + } + + const keys = enumKeys(NumberEnum); + + expect(keys).toEqual(["A", "B", "C"]); + }); + + test("returns the correct keys for string-based built-in enums", () => { + enum StringEnum { + A = "a", + B = "b", + C = "c", + } + + const keys = enumKeys(StringEnum); + expect(keys).toEqual(["A", "B", "C"]); + }); + + test("returns the correct keys for custom enums created with Enum.create", () => { + const CustomEnum = Enum.create({ + A: 1n, + B: 2n, + C: 3n, + }); + + const keys = enumKeys(CustomEnum); + expect(keys).toEqual(["A", "B", "C"]); + }); +});