Skip to content

Instantly share code, notes, and snippets.

@dyerw
Created May 4, 2021 03:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dyerw/81b52003beb7e32c9c9a4e9f39741068 to your computer and use it in GitHub Desktop.
Save dyerw/81b52003beb7e32c9c9a4e9f39741068 to your computer and use it in GitHub Desktop.
TS Type-level Fizzbuzz
type Count<A, S extends 0[] = []> = A extends S["length"]
? S
: Count<A, [...S, 0]>;
type IncC<A> = [...Count<A>, 0];
type DecC<A> = Count<A> extends [infer _H, ...(infer R)] ? R : [];
// Basic Arithmetic
type Inc<A> = IncC<A>["length"];
type Dec<A> = DecC<A>["length"];
type Add<A, B> = B extends 0 ? A : Add<Inc<A>, Dec<B>>;
type Sub<A, B> = B extends 0 ? A : Sub<Dec<A>, Dec<B>>;
type Mul<A, B, R = 0> = B extends 0 ? R : Mul<A, Dec<B>, Add<R, A>>;
type Div_<A, B, R = 0> = A extends 0 ? R : Div_<Sub<A, B>, B, Inc<R>>;
type Div<A, B> = Mul<B, Div_<A, B>> extends A
? Div_<A, B>
: Dec<Div_<A, B>>;
type Mod<A, B> = Sub<A, Mul<B, Div<A, B>>>;
// Logical operators
type Equal<A, B> = A extends B ? B extends A ? true : false : false;
type And<A, B> = A extends true ? B extends true ? true : false : false;
type Or<A, B> = A extends true
? true
: (B extends true ? true : false);
// Fizzbuzzin'
type Mod5<A> = Equal<0, Mod<A, 5>> extends true ? true : false;
type Mod3<A> = Equal<0, Mod<A, 3>> extends true ? true : false;
type Mod15<A> = And<Mod5<A>, Mod3<A>> extends true ? true : false;
type NumberToFizzBuzz<N> = Mod15<N> extends true
? "fizzbuzz"
: (Mod5<N> extends true
? "buzz"
: (Mod3<N> extends true
? "fizz"
: N));
type FizzBuzzTo<N, R extends any[] = []> = N extends 0
? R
: FizzBuzzTo<Dec<N>, [NumberToFizzBuzz<N>, ...R]>
type FizzBuzz = FizzBuzzTo<29>; // breaks after 29, foiled by the type instantiation limit
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment