## TypeScript

### It's 2 AM! Time to FizzBuzz

You can do a lot of dumb things with TypeScript, so let's do it! Here comes FizzBuzz!

I did it! I made FizzBuzz in TypeScript! And no, of course we're not using the runtime to calculate it. We're using the *type system*. This actually turned out to be quite easy, and very Haskell-like. I had to make some type optimization to make the types actually resolve, such as making it tail end recursive. I didn't know the types had this optimization, but I would end up with a stack overflow otherwise, so *I guess so*.

The idea is very simple:

- Have a tuple of digits representing the numbers.
- Use an arbitrary function for incrementing each number, mimicking the arithmetic operation.
- Create a tuple of all the numbers from 0 to 99.
- FizzBuzz every multiple of 3, 5, and 15

You can play around with it at the TypeScript Playground. There's a complaint about a possibly infinite type but it's able to resolve it, which is the only thing that matters.

`type Digit = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9; type Inc<N extends Digit> = N extends 0 ? 1 : N extends 1 ? 2 : N extends 2 ? 3 : N extends 3 ? 4 : N extends 4 ? 5 : N extends 5 ? 6 : N extends 6 ? 7 : N extends 7 ? 8 : N extends 8 ? 9 : never; type Next<A extends [Digit, Digit]> = A extends [9, 9] ? never : A extends [infer X extends Digit, infer Y extends Digit] ? Y extends 9 ? [Inc<X>, 0] : [X, Inc<Y>] : never; type DigitsString<A> = A extends [infer X extends Digit, infer Y extends Digit] ? `${X extends 0 ? "" : X}${Y}` : never; type PickEvery< V extends [Digit, Digit], Every extends [Digit, Digit], Counter extends [Digit, Digit], U > = Counter extends Every ? Next<V> extends never ? U : PickEvery<Next<V>, Every, [0, 1], V | U> : PickEvery<Next<V>, Every, Next<Counter>, U>; type Multiple<X extends [Digit, Digit]> = PickEvery<X, X, X, never>; type Threes = Multiple<[0, 3]>; type Fives = Multiple<[0, 5]>; type Fifteens = Multiple<[1, 5]>; type From0To99<A extends [Digit, Digit], Acc extends string[]> = [ Digit, Digit ] extends A ? never : Next<A> extends never ? [...Acc, "Fizz"] : A extends Fifteens ? From0To99<Next<A>, [...Acc, "FizzBuzz"]> : A extends Fives ? From0To99<Next<A>, [...Acc, "Buzz"]> : A extends Threes ? From0To99<Next<A>, [...Acc, "Fizz"]> : From0To99<Next<A>, [...Acc, DigitsString<A>]>; type FizzBuzz = From0To99<[0, 0], []>;`