Skip to content

Commit 4d936d7

Browse files
committed
add EveryCombination type
1 parent 046204a commit 4d936d7

File tree

2 files changed

+53
-0
lines changed

2 files changed

+53
-0
lines changed

src/types/Array.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

test/types/Array.spec.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { exactly } from '../../src/functions/misc'
22
import {
33
DimensionArray,
4+
EveryCombination,
45
IndexOf,
56
RemoveValue,
67
SortLongestStrings,
@@ -47,3 +48,10 @@ describe('RemoveValue', () => {
4748
test('DimensionArray', () => {
4849
;['', [[[[[[[[[['']]]]]]]]]], ['']] satisfies DimensionArray<string, 20>
4950
})
51+
52+
test('EveryCombination', () => {
53+
exactly<
54+
[1, 2, 3] | [3, 2, 1] | [2, 3, 1] | [2, 1, 3] | [3, 1, 2] | [1, 3, 2],
55+
EveryCombination<[1, 2, 3]>
56+
>
57+
})

0 commit comments

Comments
 (0)