Skip to content

Instantly share code, notes, and snippets.

@minajevs
Created January 31, 2019 09:25
Show Gist options
  • Save minajevs/cd1657462bec5baf57789d9dbf9228bf to your computer and use it in GitHub Desktop.
Save minajevs/cd1657462bec5baf57789d9dbf9228bf to your computer and use it in GitHub Desktop.
fizzbuzz types
type StringBool = "true" | "false";
interface AnyNumber { prev?: any, isZero: StringBool };
interface PositiveNumber { prev: any, isZero: "false" };
type IsZero<TNumber extends AnyNumber> = TNumber["isZero"];
type Next<TNumber extends AnyNumber> = { prev: TNumber, isZero: "false" };
type Prev<TNumber extends PositiveNumber> = TNumber["prev"];
type Add<T1 extends AnyNumber, T2> = { "true": T2, "false": Next<Add<Prev<T1>, T2>> }[IsZero<T1>];
// Computes T1 * T2
type Mult<T1 extends AnyNumber, T2 extends AnyNumber> = MultAcc<T1, T2, _0>;
type MultAcc<T1 extends AnyNumber, T2, TAcc extends AnyNumber> =
{ "true": TAcc, "false": MultAcc<Prev<T1>, T2, Add<TAcc, T2>> }[IsZero<T1>];
// Computes max(T1 - T2, 0).
type Subt<T1 extends AnyNumber, T2 extends AnyNumber> =
{ "true": T1, "false": Subt<Prev<T1>, Prev<T2>> }[IsZero<T2>];
interface SubtResult<TIsOverflow extends StringBool, TResult extends AnyNumber> {
isOverflowing: TIsOverflow;
result: TResult;
}
// Returns a SubtResult that has the result of max(T1 - T2, 0) and indicates whether there was an overflow (T2 > T1).
type SafeSubt<T1 extends AnyNumber, T2 extends AnyNumber> =
{
"true": SubtResult<"false", T1>,
"false": {
"true": SubtResult<"true", T1>,
"false": SafeSubt<Prev<T1>, Prev<T2>>
}[IsZero<T1>]
}[IsZero<T2>];
type _0 = { isZero: "true" };
type _1 = Next<_0>;
type _2 = Next<_1>;
type _3 = Next<_2>;
type _4 = Next<_3>;
type _5 = Next<_4>;
type _6 = Next<_5>;
type _7 = Next<_6>;
type _8 = Next<_7>;
type _9 = Next<_8>;
type _10 = Next<_9>;
type _11 = Next<_10>;
type _12 = Next<_11>;
type _13 = Next<_12>;
type _14 = Next<_13>;
type _15 = Next<_14>;
type _16 = Next<_15>;
type _17 = Next<_16>;
type _18 = Next<_17>;
type _19 = Next<_18>;
type _20 = Next<_19>;
type Digits = { 0: _0, 1: _1, 2: _2, 3: _3, 4: _4, 5: _5, 6: _6, 7: _7, 8: _8, 9: _9, 10: _10, 11: _11, 12: _12, 13: _13, 14: _14, 15: _15, 16: _16, 17: _17, 18: _18, 19: _19, 20: _20 };
type Digit = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20;
type NumberToType<TNumber extends Digit> = Digits[TNumber];
type _100 = Mult<_10, _10>;
type Dec2<T2 extends Digit, T1 extends Digit>
= Add<Mult<_10, NumberToType<T2>>, NumberToType<T1>>;
type Mod<TNumber extends AnyNumber, TModNumber extends AnyNumber> =
{
"true": _0,
"false": Mod2<TNumber, TModNumber, SafeSubt<TNumber, TModNumber>>
}[IsZero<TNumber>];
type Mod2<TNumber extends AnyNumber, TModNumber extends AnyNumber, TSubtResult extends SubtResult<any, any>> =
{
"true": TNumber,
"false": Mod<TSubtResult["result"], TModNumber>
}[TSubtResult["isOverflowing"]];
type Equals<TNumber1 extends AnyNumber, TNumber2 extends AnyNumber>
= Equals2<TNumber1, TNumber2, SafeSubt<TNumber1, TNumber2>>;
type Equals2<TNumber1 extends AnyNumber, TNumber2 extends AnyNumber, TSubtResult extends SubtResult<any, any>> =
{
"true": "false",
"false": IsZero<TSubtResult["result"]>
}[TSubtResult["isOverflowing"]];
// DIV
type Divisable<TNum extends Digit, TBase extends Digit> =
DivisableNumb<NumberToType<TNum>, NumberToType<TBase>>
type DivisableNumb<TNum extends AnyNumber, TBase extends AnyNumber> =
Equals<Mod<TNum, TBase>, _0>
type FizzBuzz<TNum extends Digit> =
Divisable<TNum, 15> extends "true" ? "FizzBuzz" :
Divisable<TNum, 3> extends "true" ? "Fizz" :
Divisable<TNum, 5> extends "true" ? "Buzz" :
TNum
// TEST
let fb1: FizzBuzz<1>
let fb2: FizzBuzz<2>
let fb3: FizzBuzz<3>
let fb4: FizzBuzz<4>
let fb5: FizzBuzz<5>
let fb6: FizzBuzz<6>
let fb7: FizzBuzz<7>
let fb8: FizzBuzz<8>
let fb9: FizzBuzz<9>
let fb10: FizzBuzz<10>
let fb11: FizzBuzz<11>
let fb12: FizzBuzz<12>
let fb13: FizzBuzz<13>
let fb14: FizzBuzz<14>
let fb15: FizzBuzz<15>
let fb16: FizzBuzz<16>
let fb17: FizzBuzz<17>
let fb18: FizzBuzz<18>
let fb19: FizzBuzz<19>
let fb20: FizzBuzz<20>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment