-
-
Save vit0rr/5dfa0eee2778f39496b59ad487ce7084 to your computer and use it in GitHub Desktop.
FizzBuzz made in typelevel
This file contains 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
type Reverse<A> = | |
`${A}` extends `${infer AH}${infer AT}` | |
? `${Reverse<AT>}${AH}` : A | |
type Digs = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] | |
type DigsNext<I = Digs, R = {}> = | |
I extends [infer Head, infer Next, ...infer Tail] | |
? DigsNext<[Next, ...Tail], R & Record<Head, Next>> | |
: { [K in keyof R]: R[K] } | |
type DigsPrev = { [K in keyof DigsNext as DigsNext[K]]: K } | |
type AddOne<A> = | |
A extends `${infer AH}${infer AT}` | |
? AH extends '9' ? `0${AddOne<AT>}` : `${DigsNext[AH]}${AT}` | |
: `1` | |
type SubOne<A> = | |
A extends `${infer AH}${infer AT}` | |
? AH extends '0' ? `9${SubOne<AT>}` : `${DigsPrev[AH]}${AT}` | |
: never | |
type Add<A, B> = | |
A extends `${infer AH}${infer AT}` ? | |
B extends `${infer BH}${infer BT}` | |
? BH extends '0' ? `${AH}${Add<AT, BT>}` : Add<AddOne<A>, SubOne<B>> | |
: A : B | |
type Mul<A, B, R = '0'> = | |
A extends '0' ? R : | |
B extends '0' ? R : | |
A extends `${infer AH}${infer AT}` | |
? AH extends '0' ? Mul<AT, `0${B}`, R> : Mul<SubOne<A>, B, Add<R, B>> | |
: R | |
type Multiply<A extends string | number | bigint, B extends string | number | bigint> = | |
Reverse<Mul<Reverse<A>, Reverse<B>>> | |
type Division< | |
W extends number, | |
D extends number, | |
Error extends any = never, | |
Q extends string = '0' | |
> = | |
W extends 0 | |
? Q extends never ? Error : Q | |
: W extends never ? Error : Division<Subtract<W, D>, D, Error, AddOne<Q>> | |
type ConstructTuple< | |
L extends number, | |
R extends unknown[] = [] | |
> = R["length"] extends L | |
? R | |
: ConstructTuple<L, [...R, unknown]> | |
type Subtract< | |
M extends number, | |
S extends number | |
> = ConstructTuple<M> extends [...subtrahend: ConstructTuple<S>, ...rest: infer Rest] | |
? Rest["length"] | |
: never | |
const div: Division<9, 3> = "3" | |
const div: Division<15, 3> = "5" | |
type FizzBuzzValidator< | |
V extends number | |
> = | |
Division<V, 3> extends never | |
? never | |
: Division<V, 5> extends never | |
? never | |
: 'FizzBuzz' | |
type BuzzValidator< | |
V extends number | |
> = | |
Division<V, 3> extends never | |
? never | |
: 'Buzz' | |
type FizzValidator< | |
V extends number | |
> = | |
Division<V, 5> extends never | |
? never | |
: 'Fizz' | |
type FizzBuzz | |
<V extends number> = | |
FizzBuzzValidator<V> extends never | |
? FizzValidator<V> extends never | |
? BuzzValidator<V> extends never | |
? V | |
:'Buzz' | |
:'Fizz' | |
:'FizzBuzz' | |
const res: FizzBuzz<2> // 2 | |
const buzz: FizzBuzz<3> // Buzz | |
const fizz: FizzBuzz<5> // Fizz | |
const fizzBuzz: FizzBuzz<15> // FizzBuzz | |
type FizzBuzzArr< | |
V extends Array<number>, | |
A extends Array<any> = [] | |
> = | |
V extends [infer E, ...infer D] | |
? FizzBuzzArr<D, [...A, ...[FizzBuzz<E>]]> | |
: A | |
const FIZZBUZZZZ: FizzBuzzArr<[1,2,3,4,5,6,7,8,9, 15]> // [1, 2, "Buzz", 4, "Fizz", "Buzz", 7, 8, "Buzz", "FizzBuzz"] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment