@@ -272,3 +272,48 @@ export type DimensionArray<T, Dimension extends number> = (
272272 | T
273273 | ( Dimension extends 0 ? never : DimensionArray < T , Decrement < Dimension > > )
274274) [ ]
275+
276+ /**
277+ * for some reason the ts toolbelt Tail causes a recursion error in the {@link EveryCombination}
278+ * types so i made this one instead
279+ */
280+ // TODO: figure out what's up with the ts-toolbelt Tail type, should i just export and use this one everywhere instead?
281+ type Tail2 < T extends unknown [ ] > = number extends T [ 'length' ] ? never : Splice < T , 0 , 1 >
282+
283+ type InsertIntoEachIndexInArray <
284+ T extends unknown [ ] ,
285+ ToAdd ,
286+ Count extends number ,
287+ > = number extends T [ 'length' ]
288+ ? never
289+ : [
290+ Splice < T , Count , 0 , [ ToAdd ] > ,
291+ ...( Count extends T [ 'length' ] ? [ ] : InsertIntoEachIndexInArray < T , ToAdd , Add < Count , 1 > > ) ,
292+ ]
293+
294+ type AddToCombinations < T extends unknown [ ] [ ] , ToAdd > = T extends [ ]
295+ ? [ ]
296+ : [
297+ ...InsertIntoEachIndexInArray < T [ 0 ] , ToAdd , 0 > ,
298+ ...( Tail2 < T > extends infer Narrowed extends unknown [ ] [ ]
299+ ? AddToCombinations < Narrowed , ToAdd >
300+ : never ) ,
301+ ]
302+
303+ type _EveryCombination < T extends unknown [ ] , Result extends unknown [ ] [ ] = [ [ T [ 0 ] ] ] > = T extends [ ]
304+ ? [ ]
305+ : T extends [ unknown ]
306+ ? Result
307+ : AddToCombinations < Result , T [ 1 ] > extends infer Narrowed extends unknown [ ] [ ]
308+ ? _EveryCombination < Tail2 < T > , Narrowed >
309+ : never
310+
311+ /**
312+ * creates a union type of every possible combination of values in the `T` array type, excluding
313+ * duplicates.
314+ *
315+ * if you want to allow duplicates, do something like `TupleOf<T[number], T['length']>`
316+ */
317+ export type EveryCombination < T extends unknown [ ] > = _EveryCombination < T > extends infer Result
318+ ? Result [ number & keyof Result ]
319+ : never
0 commit comments