Skip to content

Instantly share code, notes, and snippets.

@betafcc
Last active September 5, 2022 10:57
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save betafcc/827814d341522f8f74cc4b0df1d1e1a1 to your computer and use it in GitHub Desktop.
Save betafcc/827814d341522f8f74cc4b0df1d1e1a1 to your computer and use it in GitHub Desktop.
Type-Level FizzBuzz in Typescript
// Iterator approach, seems to be good up until ~850
type Result = Take<100, FizzBuzzIterator[1]>
// ["1", "2", "Fizz", "4", "Buzz", "Fizz", "7", "8", "Fizz", "Buzz", "11", "Fizz", "13", "14", "FizzBuzz", ...]
export type FizzBuzzIterator<
S extends Record<any, any> = { 3: []; 5: []; i: [] },
R extends string = `${S[3]["length"] extends 3 ? "Fizz" : ""}${S[5]["length"] extends 5 ? "Buzz" : ""}`
> = [
R extends "" ? `${S["i"]["length"]}` : R,
FizzBuzzIterator<{
3: S[3]["length"] extends 3 ? [1] : [...S[3], 1]
5: S[5]["length"] extends 5 ? [1] : [...S[5], 1]
i: [...S["i"], 1]
}>
]
type Take<N extends number, Cons extends [any, any], Acc extends any[] = []>
= Acc["length"] extends N ? Acc : Take<N, Cons[1], [...Acc, Cons[0]]>
// Normal recursive approach, seems to be good up until ~850
type Result = FizzBuzzRange<1, 101>
// ["1", "2", "Fizz", "4", "Buzz", "Fizz", "7", "8", "Fizz", "Buzz", "11", "Fizz", "13", "14", "FizzBuzz", ...]
export type FizzBuzzRange<A extends number, B extends number, Acc extends any[] = []>
= A extends B ? Acc : FizzBuzzRange<Add<A, 1>, B, [...Acc, FizzBuzz<A>]>
export type FizzBuzz<
X extends number,
S extends string = `${Div<X, 3> extends true ? "Fizz" : ""}${Div<X, 5> extends true ? "Buzz" : ""}`
> = S extends "" ? `${X}` : S
type Div<A extends number, B extends number, Acc extends number = B>
= A extends Acc ? true : Lt<A, Acc> extends true ? false : Div<A, B, Add<Acc, B>>
type Add<A extends number, B extends number> = Extract<[...Range<A>, ...Range<B>]["length"], number>
type Range<N extends number, Acc extends number[] = []>
= Acc["length"] extends N ? Acc : Range<N, [...Acc, Acc["length"]]>
type Lt<A extends number, B extends number, R extends number[] = Range<B>> = A extends R[number] ? true : false
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment