Created
April 29, 2022 05:46
-
-
Save evinism/c1d1a9da6c8e07d6705b00d7b92049b4 to your computer and use it in GitHub Desktop.
Type-level FizzBuzz in Typescript
This file contains hidden or 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
/* Summon the naturals */ | |
type Zero = 0; | |
type Succ<T extends Succ<any> | Zero> = { | |
next: T; | |
} | |
// Construct a few naturals. | |
type n0 = Zero; | |
type n1 = Succ<n0>; | |
type n2 = Succ<n1>; | |
type n3 = Succ<n2>; | |
type n4 = Succ<n3>; | |
type n5 = Succ<n4>; | |
// and so on... | |
// Continued in appendix. | |
// And some basic subtracty operations | |
type Pred<T> = T extends Succ<infer N> ? N : never; | |
type MathError = {error: "math error!"}; | |
type Subtract<A, B> = | |
B extends n0 | |
? A | |
: ( | |
A extends n0 | |
? MathError | |
: Subtract<Pred<A>, Pred<B>> | |
); | |
type EvenlyDividedBy<A, B> = | |
A extends MathError | |
? false | |
: ( | |
A extends n0 | |
? true | |
: EvenlyDividedBy<Subtract<A, B>, B> | |
) | |
// And given our utils, finish the job | |
type FizzBuzz<N> = | |
EvenlyDividedBy<N, n15> extends true | |
? "fizzbuzz" | |
: ( | |
EvenlyDividedBy<N, n3> extends true | |
? "fizz" | |
: ( | |
EvenlyDividedBy<N, n5> extends true | |
? "buzz" | |
: N | |
) | |
); | |
// Our job is complete | |
type f45 = FizzBuzz<n45>; | |
type f46 = FizzBuzz<n46>; | |
type f47 = FizzBuzz<n47>; | |
type f48 = FizzBuzz<n48>; | |
// Appendix: A Bunch of Numbers | |
type n6 = Succ<n5>; | |
type n7 = Succ<n6>; | |
type n8 = Succ<n7>; | |
type n9 = Succ<n8>; | |
type n10 = Succ<n9>; | |
type n11 = Succ<n10>; | |
type n12 = Succ<n11>; | |
type n13 = Succ<n12>; | |
type n14 = Succ<n13>; | |
type n15 = Succ<n14>; | |
type n16 = Succ<n15>; | |
type n17 = Succ<n16>; | |
type n18 = Succ<n17>; | |
type n19 = Succ<n18>; | |
type n20 = Succ<n19>; | |
type n21 = Succ<n20>; | |
type n22 = Succ<n21>; | |
type n23 = Succ<n22>; | |
type n24 = Succ<n23>; | |
type n25 = Succ<n24>; | |
type n26 = Succ<n25>; | |
type n27 = Succ<n26>; | |
type n28 = Succ<n27>; | |
type n29 = Succ<n28>; | |
type n30 = Succ<n29>; | |
type n31 = Succ<n30>; | |
type n32 = Succ<n31>; | |
type n33 = Succ<n32>; | |
type n34 = Succ<n33>; | |
type n35 = Succ<n34>; | |
type n36 = Succ<n35>; | |
type n37 = Succ<n36>; | |
type n38 = Succ<n37>; | |
type n39 = Succ<n38>; | |
type n40 = Succ<n39>; | |
type n41 = Succ<n40>; | |
type n42 = Succ<n41>; | |
type n43 = Succ<n42>; | |
type n44 = Succ<n43>; | |
type n45 = Succ<n44>; | |
type n46 = Succ<n45>; | |
type n47 = Succ<n46>; | |
type n48 = Succ<n47>; | |
type n49 = Succ<n48>; | |
type n50 = Succ<n49>; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment