Skip to content

Commit

Permalink
Improve typings for enums
Browse files Browse the repository at this point in the history
  • Loading branch information
thegedge committed Feb 24, 2024
1 parent 02ee34d commit 6c37a7f
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 10 deletions.
18 changes: 18 additions & 0 deletions __tests__/core/type-system.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1210,3 +1210,21 @@ test("union type inference verification for a large number of types", () => {
assertTypesEqual(_ as ITC, _ as "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j")
assertTypesEqual(_ as ITS, _ as "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j")
})

test("enumeration type inference verification", () => {
const HexLetter = types.enumeration("HexadecimalLetter", ["a", "b", "c", "d", "e", "f"])

type LetterITC = SnapshotIn<typeof HexLetter>
type LetterITS = SnapshotOut<typeof HexLetter>

assertTypesEqual(_ as LetterITC, _ as "a" | "b" | "c" | "d" | "e" | "f")
assertTypesEqual(_ as LetterITS, _ as "a" | "b" | "c" | "d" | "e" | "f")

const Digit = types.enumeration(["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"])

type DigitITC = SnapshotIn<typeof Digit>
type DigitITS = SnapshotOut<typeof Digit>

assertTypesEqual(_ as DigitITC, _ as "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9")
assertTypesEqual(_ as DigitITS, _ as "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9")
})
17 changes: 7 additions & 10 deletions src/types/utility-types/enumeration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,11 @@ export type UnionStringArray<T extends readonly string[]> = T[number]
// these overloads also allow both mutable and immutable arrays, making types.enumeration<Enum>(Object.values(Enum)) possible.
// the only case where this doesn't work is when passing to the function an array variable with a mutable type constraint;
// for these cases, it will just fallback and assume the type is a generic string.
export function enumeration<T extends readonly string[]>(
options: T
): ISimpleType<UnionStringArray<T>>
export function enumeration<T extends string>(options: T[]): ISimpleType<UnionStringArray<T[]>>
export function enumeration<T extends string>(
name: string,
options: T[]
): ISimpleType<UnionStringArray<T[]>>

/**
* `types.enumeration` - Can be used to create an string based enumeration.
* (note: this methods is just sugar for a union of string literals)
Expand All @@ -31,11 +28,11 @@ export function enumeration<T extends string>(
* @param options possible values this enumeration can have
* @returns
*/
export function enumeration<OptionsT extends any[]>(
name: string | string[],
options?: OptionsT
): ISimpleType<string> {
const realOptions: string[] = typeof name === "string" ? options! : name
export function enumeration<T extends string[]>(
name: string | T,
options?: T
): ISimpleType<T[number]> {
const realOptions: T = typeof name === "string" ? options! : name
// check all options
if (devMode()) {
realOptions.forEach((option, i) => {
Expand All @@ -44,5 +41,5 @@ export function enumeration<OptionsT extends any[]>(
}
const type = union(...realOptions.map((option) => literal("" + option)))
if (typeof name === "string") type.name = name
return type
return type as ISimpleType<T[number]>
}

0 comments on commit 6c37a7f

Please sign in to comment.