Skip to content

Instantly share code, notes, and snippets.

@karol-majewski
Last active November 30, 2020 01:21
Show Gist options
  • Save karol-majewski/39d7f10c803162d7e9d17106b1947cd7 to your computer and use it in GitHub Desktop.
Save karol-majewski/39d7f10c803162d7e9d17106b1947cd7 to your computer and use it in GitHub Desktop.
Type-level addition in TypeScript (2 methods)
interface Increments {
0: 1;
1: 2;
2: 3;
3: 4;
4: 5;
}
interface Decrements {
1: 0;
2: 1;
3: 2;
4: 3;
5: 4;
}
type Increment<T extends number> = T extends keyof Increments ? Increments[T] : never;
type Decrement<T extends number> = T extends keyof Decrements ? Decrements[T] : never;
type Add<T extends number, U extends number> = {
finish: U;
continue: Add<Decrement<T>, Increment<U>>;
}[T extends 0 ? 'finish' : 'continue'];
type Five = Add<2, 3>;
@karol-majewski
Copy link
Author

karol-majewski commented Nov 30, 2020

A solution without truth tables:

type TupleLike<T = unknown> = T[] | [T];

type TupleOf<T, N extends number> = N extends N ? (number extends N ? T[] : _TupleOf<T, N, []>) : never;
type _TupleOf<T, N extends number, R extends unknown[]> = R['length'] extends N ? R : _TupleOf<T, N, [T, ...R]>;

type Increment<T extends number> = [...TupleOf<unknown, T>, unknown]['length']
type Decrement<T extends number> = TupleOf<unknown, T> extends [unknown, ...infer U] ? U['length'] : never;

type Add<T extends number, U extends number> = {
  finish: U;
  continue: Add<Decrement<T>, Extract<Increment<U>, number>>;
}[T extends 0 ? 'finish' : 'continue'];

type Five = Add<2, 3>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment