Skip to content

Instantly share code, notes, and snippets.

@gabrielelana
Created August 8, 2023 10:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gabrielelana/d09ab0f3a6b976dd25fb2f484d967c56 to your computer and use it in GitHub Desktop.
Save gabrielelana/d09ab0f3a6b976dd25fb2f484d967c56 to your computer and use it in GitHub Desktop.
Compute all ordered combinations of a list of values at compile type in TypeScript
type Tuple<X, Y> = [X, Y]
type Equal<X, Y> =
(<T>() => T extends X ? 1 : 2) extends
(<T>() => T extends Y ? 1 : 2) ? Tuple<true, Y> : Tuple<false, Y>
type Assert<T extends Tuple<true, any>> = T[1];
type AppendToAll<X, A extends Array<Array<any>>, R extends Array<any> = []> =
A extends []
? R
: A extends [infer H extends Array<any>, ...infer T extends Array<Array<any>>]
? AppendToAll<X, T, [...R, [X, ...H]]>
: never;
type CombinationsOf<A extends Array<any>> =
A extends []
? [[]]
: A extends [infer H, ...infer T]
? T extends []
? [...CombinationsOf<T>, [H]]
: [...CombinationsOf<T>, ...AppendToAll<H, CombinationsOf<T>>]
: never
type PermutationsOf<A extends Array<any>, L extends Array<any> = [], R extends Array<any> = []> =
A extends []
? R extends []
? [[]]
: R
: A extends [infer H, ...infer T]
? PermutationsOf<T, [H, ...L], [...R, ...AppendToAll<H, PermutationsOf<[...L, ...T]>>]>
: never;
type ToUnionOfAll<A extends Array<any>, R extends any = never> =
A extends []
? R
: A extends [infer H, ...infer T] ? ToUnionOfAll<T, H | R> : never;
type PermutationsOfAll<A extends Array<any>, R extends Array<any> = []> =
A extends []
? R
: A extends [infer H extends Array<any>, ...infer T]
? PermutationsOfAll<T, [...R, ...PermutationsOf<H>]>
: never;
type CombinationsOfAsUnion<A extends Array<any>> = ToUnionOfAll<PermutationsOfAll<CombinationsOf<A>>>;
export type _ = [
Assert<Equal<[], CombinationsOfAsUnion<[]>>>,
Assert<Equal<[] | [1], CombinationsOfAsUnion<[1]>>>,
Assert<Equal<[] | [1] | [2] | [1, 2] | [2, 1], CombinationsOfAsUnion<[1, 2]>>>,
Assert<Equal<[] | [1] | [2] | [3] | [1, 2] | [2, 1] | [1, 3] | [2, 3] | [3, 1] | [3, 2] | [1, 2, 3] | [1, 3, 2] | [2, 1, 3] | [2, 3, 1] | [3, 2, 1] | [3, 1, 2], CombinationsOfAsUnion<[1, 2, 3]>>>,
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment