Skip to content

Instantly share code, notes, and snippets.

@rjdestigter
Last active May 31, 2021 15:38
Show Gist options
  • Save rjdestigter/64eaec0fcdb003bff1cad2000c787efd to your computer and use it in GitHub Desktop.
Save rjdestigter/64eaec0fcdb003bff1cad2000c787efd to your computer and use it in GitHub Desktop.
type Digit = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
type IsNumber<A extends string> = A extends `${Digit}${infer T}` ? T extends "" ? true : IsNumber<T> : false
type NaN = "NaN"
type ToLiteralNumber<T extends string> = IsNumber<T> extends true ? MkTuple<T> extends true[] ? MkTuple<T>['length'] : NaN : NaN
type MkTuple<N extends string | number, T extends true[] = []> = `${T['length']}` extends `${N}` ? T : MkTuple<N, [true, ...T]>
type Add<A extends number, B extends number> = [...MkTuple<A>, ...MkTuple<B>]['length']
type SubtractOne<A extends number> = MkTuple<A> extends [infer _, ...infer R] ? R['length'] : 0
type Subtract<A extends number, B extends number> = B extends 0 ? A : Subtract<SubtractOne<A>, SubtractOne<B>>
type IsGreaterThenOrEqual<A extends number, B extends number> =
A extends 0 ? B extends 0 ? true : false : A extends B ? true : IsGreaterThenOrEqual<SubtractOne<A>, B>
type IsGreaterThen<A extends number, B extends number> =
A extends B ? false : IsGreaterThenOrEqual<SubtractOne<A>, B>
type Multiply<A extends number, B extends number, R extends number = B> =
A extends 0
? 0
: B extends 0
? 0
: A extends 1
? R
: B extends 1
? R
: Add<R, B> extends number
? Multiply<SubtractOne<A>, B, Add<R, B>>
: B
type Fraction<L extends number, N extends number, D extends number> = [L, N, D]
type AnyFraction = Fraction<number, number, number>
type Rest<A extends number, B extends number> = [A, B]
type DivideWithRest<A extends number, B extends number, Acc extends number = 0> = A extends B
? Add<Acc, 1> extends number ? Rest<Add<Acc, 1>, 0> : 0
: IsGreaterThen<B, A> extends true
? Rest<Acc, A>
: Add<Acc, 1> extends number ? DivideWithRest<Subtract<A, B>, B, Add<Acc, 1>> : never
// [result, rest, divisor]
type Divide<A extends number, B extends number> = DivideWithRest<A, B> extends infer Result ? Result extends Rest<infer T, infer U> ? Fraction<T, U, B> : Result : never
type GetDecimals<T extends AnyFraction, Level extends number = 0> = Level extends 4 ? [] : T extends [infer L, infer N, infer D]
? N extends number
? D extends number
? N extends 0
? [L]
: Multiply<N, 10> extends number
? Divide<Multiply<N, 10>, D> extends [number, number, number]
? Add<1, Level> extends number ? [L, ...GetDecimals<Divide<Multiply<N, 10>, D>, Add<1, Level>>] : never
: []
: []
: []
: never
: never
type Join<A extends number[]> = A extends [infer B, ...infer C] ? B extends number ? `${B}${C extends number[] ? Join<C> : ""}` : "" : ""
type ShowFraction<T extends AnyFraction> = GetDecimals<T> extends [infer L, ...infer D] ? L extends number ? D extends number[] ? `${L}.${Join<D>}` : never : never : never
type expr0_25 = ShowFraction<[0, 1, 4]>
type expr1_333 = ShowFraction<Divide<4, 3>>
type expr25 = Add<12, 13>
type expr15 = Subtract<20, 5>
type exprTrue = IsGreaterThen<Add<25, 1>, 25>
type expr8 = Multiply<2, 4>
declare const fifteen : Multiply<3, 5>
const fifteen_ : Multiply<5, 3> = fifteen
const fifteen__ : Add<7, 8> = fifteen
const fifteen___ : Divide<30, 2>[0] = fifteen
const fifteen____ : Subtract<21, 6> = fifteen
type expr84_seems_to_be_max = Add<42, 42>
type expr42 = ToLiteralNumber<"42">
type exprNaN = ToLiteralNumber<"abc">
type expr15_ = Subtract<ToLiteralNumber<"33">, Multiply<ToLiteralNumber<"3">, 6>>
type expr27 = Add<ToLiteralNumber<"12">, Subtract<ToLiteralNumber<"33">, Multiply<ToLiteralNumber<"3">, 6>>>
function add <A extends number, B extends number>(a: A, b: B): Add<A, B> {
return (a + b) as any
}
const nine: 9 = add(4, 5)
const nine_: Multiply<3, 3> = add(4, 5)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment