Skip to content

Instantly share code, notes, and snippets.

@duarten
Created September 19, 2020 05: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 duarten/5dd8bd7caedf33283b3618cc3de8230a to your computer and use it in GitHub Desktop.
Save duarten/5dd8bd7caedf33283b3618cc3de8230a to your computer and use it in GitHub Desktop.
Compile-time permutations in TypeScript
type Access<Tuple extends readonly unknown[], I extends string> =
I extends keyof Tuple ? Tuple[I] : never
type Swap<Tuple extends readonly unknown[], I extends string, J extends string> = {
[Index in keyof Tuple]: Index extends I ? Access<Tuple, J> : Index extends J ? Access<Tuple, I> : Tuple[Index]
}
type Length<Tuple extends readonly unknown[]> = Tuple["length"] extends number ? `${Tuple["length"]}` : never
type PushFront<Tuple extends readonly unknown[], E> = [E, ...Tuple]
type Range<Size extends string, Tuple extends readonly unknown[] = []> =
Length<Tuple> extends Size ? Tuple : Range<Size, PushFront<Tuple, 0>>
type Increment<I extends string> = Length<PushFront<Range<I>, 0>>
type FixedIdx<Tuple extends readonly unknown[], I extends string, Idx extends string> =
I extends Length<Tuple> ? Tuple : Perms<Swap<Tuple, I, Idx>, Increment<Idx>> | FixedIdx<Tuple, Increment<I>, Idx>
type Perms<Tuple extends readonly unknown[], Idx extends string> =
Idx extends Length<Tuple> ? Tuple : FixedIdx<Tuple, Idx, Idx>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment