Skip to content

Instantly share code, notes, and snippets.

@briancavalier
Last active September 2, 2020 13:15
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 briancavalier/560bde143d2a0a5287d53bf69be3230e to your computer and use it in GitHub Desktop.
Save briancavalier/560bde143d2a0a5287d53bf69be3230e to your computer and use it in GitHub Desktop.
type Tuple<Iterables extends Iterable<any>[]> = {
[K in keyof Iterables]: Iterables[K] extends Iterable<infer A> ? A : never
}
export const product = <Iterables extends Iterable<any>[]>(...t: Iterables): Iterable<Tuple<Iterables>> =>
t.length === 0 ? [] : prod(t, [])
export function* prod<Iterables extends Iterable<any>[]>([h, ...t]: Iterables, r: any[]): Iterable<Tuple<Iterables>> {
if (t.length === 0) for (const a of h) yield [...r, a] as Tuple<Iterables>
else for (const a of h) yield* prod(t, [...r, a]) as Iterable<Tuple<Iterables>>
}
for (const x of product()) console.log(x)
for (const x of product([true, false])) console.log(x)
for (const x of product([true, false], ['a', 'b', 'c'])) console.log(x)
for (const x of product([true, false], ['a', 'b', 'c'], [1, 2, 3])) console.log(x)
│ ts-node ./src/iterable.ts
[ true ]
[ false ]
[ true, 'a' ]
[ true, 'b' ]
[ true, 'c' ]
[ false, 'a' ]
[ false, 'b' ]
[ false, 'c' ]
[ true, 'a', 1 ]
[ true, 'a', 2 ]
[ true, 'a', 3 ]
[ true, 'b', 1 ]
[ true, 'b', 2 ]
[ true, 'b', 3 ]
[ true, 'c', 1 ]
[ true, 'c', 2 ]
[ true, 'c', 3 ]
[ false, 'a', 1 ]
[ false, 'a', 2 ]
[ false, 'a', 3 ]
[ false, 'b', 1 ]
[ false, 'b', 2 ]
[ false, 'b', 3 ]
[ false, 'c', 1 ]
[ false, 'c', 2 ]
[ false, 'c', 3 ]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment