Skip to content

Instantly share code, notes, and snippets.

@ssippe
Created April 20, 2017 00:33
Show Gist options
  • Select an option

  • Save ssippe/1f92625532eef28be6974f898efb23ef to your computer and use it in GitHub Desktop.

Select an option

Save ssippe/1f92625532eef28be6974f898efb23ef to your computer and use it in GitHub Desktop.
Typescript Cartesian Product
const f = (a: any[], b: any[]): any[] =>
[].concat(...a.map(a2 => b.map(b2 => [].concat(a2, b2))));
export const cartesianProduct = (a: any[], b: any[], ...c: any[]) => {
if (!b || b.length === 0) {
return a;
}
const [b2, ...c2] = c;
const fab = f(a, b);
return cartesianProduct(fab, b2, c2);
};
@please-rewrite
Copy link

please-rewrite commented Oct 31, 2023

Mixed types are tricky.
Give this a try.

The key is [...T]

export const cartesianProduct = <T extends any[][]>(a: [...T]): Array<{[K in keyof T]: T[K][number]}> => a.reduce((a, b) => a.flatMap(d => b.map(e => [d, e].flat())))

@h-chal
Copy link

h-chal commented Dec 10, 2025

@please-rewrite 's version with clearer variable names:

export const cartesianProduct = <T extends any[][]>(
    arrays: [...T],
): Array<{ [K in keyof T]: T[K][number]; }> =>
    arrays.reduce((partialProduct, nextArray) =>
        partialProduct.flatMap(items =>
            nextArray.map(
                nextItem => [items, nextItem].flat(),
            )
        )
    );

@albertodiazdorado
Copy link

That solution actually works!

export const cartesianProduct = <T extends any[][]>(
  arrays: [...T],
): Array<{ [K in keyof T]: T[K][number] }> =>
  arrays.reduce((partialProduct, nextArray) =>
    partialProduct.flatMap((items) =>
      nextArray.map((nextItem) => [items, nextItem].flat()),
    ),
  );

const numbers = [1, 2, 3, 4];
const strings = ["1", "2", "3", "4"];

// const product: [number, string][]
const product = cartesianProduct([numbers, strings]);

console.log(product[0][1].length);

Thanks @please-rewrite , @h-chal ! The only awkward thing is that we must use any, but apart from that, this gets the job done :D

@cr0cK now you can compare your non-functioning solution with an actually working solution :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment