Skip to content

Instantly share code, notes, and snippets.

@acquitelol
Last active July 31, 2025 10:59
Show Gist options
  • Select an option

  • Save acquitelol/b461df30b92d3d0177cba17fb83626b8 to your computer and use it in GitHub Desktop.

Select an option

Save acquitelol/b461df30b92d3d0177cba17fb83626b8 to your computer and use it in GitHub Desktop.
A mathematical expression evaluator for natural numbers purely in the TypeScript type system
type Succ<T extends number, acc extends number[] = []> = acc['length'] extends T
? [...acc, 0]['length']
: Succ<T, [...acc, 0]>;
type Add<T extends number, U extends number, acc extends number[] = []> = acc['length'] extends U
? T
: Add<Succ<T>, U, [...acc, 0]>;
type Mul<T extends number, U extends number, Res extends number = 0, acc extends number[] = []> = acc['length'] extends U
? Res
: Mul<T, U, Add<Res, T>, [...acc, 0]>;
type Prec<T extends number, acc extends number[] = []> = [...acc, 0]['length'] extends T
? acc['length']
: Prec<T, [...acc, 0]>;
type Sub<T extends number, U extends number, acc extends number[] = []> = acc['length'] extends U
? T
: Sub<Prec<T>, U, [...acc, 0]>;
type LessThan<A extends number, B extends number, acc extends number[] = []> =
acc['length'] extends A ? true :
acc['length'] extends B ? false :
LessThan<A, B, [...acc, 0]>;
type Div<A extends number, B extends number, acc extends number[] = []> = LessThan<A, B> extends true
? [...acc, 0]['length']
: Div<Sub<A, B>, B, [...acc, 0]>;
type Eval<T extends string> = T extends `${infer A extends number} ${infer Op extends string} ${infer B extends number}`
?
Op extends '+' ? Add<A, B> :
Op extends '-' ? Sub<A, B> :
Op extends '*' ? Mul<A, B> :
Op extends '/' ? Div<A, B> :
never
: never;
type Res = Eval<'15 / 3'>; // type Res = 5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment