TypeScript 4.0 started to support the notion of Variadic Tuple Types, a nice type construct that can be used in e.g. concatenation functions. An example from the docs:
type Arr = readonly any[];
function concat<T extends Arr, U extends Arr>(arr1: T, arr2: U): [...T, ...U] {
return [...arr1, ...arr2];
}
I am interested in whether this type construct can be used to type a Cartesian Product function. The function should then infer the (mixed) types from the arguments to produce its return type. So if I input [number[], string[]] I would expect the output to be of type [number, string][]. Multiple implementations for a Cartesian Product can be found in this thread, but none is strictly typed. Here is an example:
const cartesian =
(...a) => a.reduce((a, b) => a.flatMap(d => b.map(e => [d, e].flat())));
An implementation I currently use does not utilise Variadic Tuple Types and needs explicit type casting:
const cartesian = <T extends any[]>(...arr: any[][]): T[] =>
arr.reduce<T[]>(
(a, b) => a.flatMap<T>(c => b.map<T>(d => [...c, d] as T)),
[[]] as T
);
const product = cartesian<[number, string]>([1, 2, 3], ['a', 'b', 'c']);
I am looking for a solution without explicit type casting and I think Variadic Tuple Types may be the appropriate type construct here.
Question
How can I use Variadic Tuple Types to infer the types of a Cartesian Product function?