Skip to content

Instantly share code, notes, and snippets.

@shicks
Last active October 16, 2020 10:14
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shicks/0a505c589c6a5c2755ba75e7f4324eb0 to your computer and use it in GitHub Desktop.
Save shicks/0a505c589c6a5c2755ba75e7f4324eb0 to your computer and use it in GitHub Desktop.
Parsing integers in TypeScript's type system
type NumCat<X, Y> = X extends any[] ? Y extends any[] ? [...X, ...X, ...X, ...X, ...X, ...X, ...X, ...X, ...X, ...X, ...Y] : never : never;
type OneDigit = {
'0': [], '1': [any], '2': [any, any], '3': [any, any, any],
'4': [any, any, any, any], '5': [any, any, any, any, any],
'6': [any, any, any, any, any, any], '7': [any, any, any, any, any, any, any],
'8': [any, any, any, any, any, any, any, any],
'9': [any, any, any, any, any, any, any, any, any],
};
type Digit<S> = S extends keyof OneDigit ? OneDigit[S] : never;
type Len<X> = X extends any[] ? X['length'] : never;
type Chars<X extends string> = X extends `${infer A}${infer B}` ? [A, ...Chars<B>] : [];
type ListStr<X extends any[]> =
X extends [any, ...any] ? X extends [...infer tens, infer ones] ? NumCat<ListStr<tens>, Digit<ones>> : never : [];
type Num<X extends string> = Len<ListStr<Chars<X>>>;
type Anys<X> = X extends [any, ...infer U] ? [any, ...Anys<[...U]>] : [];
type _Cmp<X, Y> = X extends [...Anys<Y>, ...any[]] ? Y extends [...Anys<X>, ...any[]] ? _Cmp1<X, Y> : 'gt' : 'lt';
type _Cmp1<X, Y> = X extends [] ? 'eq' : X extends [infer X1, ...infer X2] ? Y extends [infer Y1, ...infer Y2] ? _Cmp2<Digit<X1>, Digit<Y1>, X2, Y2> : never : never;
type _Cmp2<X1 extends any[], Y1 extends any[], X2, Y2> = X1 extends [...Y1, ...any[]] ? Y1 extends [...X1, ...any[]] ? _Cmp1<X2, Y2> : 'gt' : 'lt';
type Cmp<X extends number, Y extends number> = _Cmp<Chars<`${X}`>, Chars<`${Y}`>>;
type Tail<L> = L extends [any, ...infer U] ? U : {tail: L};
type List<N extends number> = N extends 0 ? [] : _List<N, [[any]]>;
type _List<N extends number, L extends any[][]> = _List1<N, L, Cmp<N, L[0]['length']>>;
type _List1<N extends number, L extends any[][], C> = C extends 'eq' ? L[0] : C extends 'lt' ? _List2<N, Tail<L>, []> : _List<N, [[...L[0], ...L[0]], ...L]>;
type _List2<N extends number, L, O extends any[]> = L extends any[][] ? _List3<N, L, O> : {N: N, L: L, O: O};
type _List3<N extends number, L extends any[][], O extends any[]> = _List4<N, L, O, [...L[0], ...O]>;
type _List4<N extends number, L extends any[][], O1 extends any[], O2 extends any[]> =
_List5<N, L, O1, O2, Cmp<N, O2['length']>>;
type _List5<N extends number, L extends any[][], O1 extends any[], O2 extends any[], C> =
C extends 'eq' ? O2 : C extends 'gt' ? _List2<N, Tail<L>, O2> : _List2<N, Tail<L>, O1>
type Add<X extends number, Y extends number> = Len<[...List<X>, ...List<Y>]>;
type Mul<X extends number, Y extends number> = Len<_Mul<List<X>, List<Y>>>;
type _Mul<X extends any[], Y extends any[]> = X extends [any, ...infer U] ? [...Y, ..._Mul<U, Y>] : [];
// Usage:
type five = Num<'5'>;
type twelveHundred = Num<'1200'>;
type sum = Add<123, 434>;
type product = Mul<23, 53>;
@shicks
Copy link
Author

shicks commented Oct 12, 2020

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