I am currently developing a combinations function that generates a cartesian product of input lists. A unique feature I want to include is the ability to support enums as potential lists, with the possibility of expanding to support actual Sets in the future.
Here is the code snippet that has been proven to work:
type EnumOrArray = { [key: string]: any; } | any[];
export function cartesian(...inputs: EnumOrArray[]): any[][] {
const itemGroups: any[][] = inputs.map(input => {
if (Array.isArray(input)) {
return input; // Return directly if input is an array
} else {
// Extract enum keys and convert them to numeric values
const originalKeys = Object.keys(input).filter(key => isNaN(Number(key)));
return originalKeys.map(key => input[key]);
}
});
// Recursive function for generating combinations (remains unchanged)
function generateCartesianProduct(groups: any[][], prefix: any[] = []): any[][] {
if (!groups.length) return [prefix];
const firstGroup = groups[0];
const restGroups = groups.slice(1);
let result: any[][] = [];
firstGroup.forEach(item => {
result = result.concat(generateCartesianProduct(restGroups, [...prefix, item]));
});
return result;
}
return generateCartesianProduct(itemGroups);
}
However, the issue lies in the fact that this setup acts like a type firewall and only produces output of type any[][]
, which is not ideal.
For instance, when using the above code with enums like this:
enum Color {
Red = 'red',
Green = 'green',
Blue = 'blue'
}
enum Size {
Small = 1,
Medium = 10,
Large = 100
}
const numbers = [1, 2];
const combos = cartesian(Color, numbers, Size);
The output generated is correct:
[
[ 'red', 1, 1 ], [ 'red', 1, 10 ],
[ 'red', 1, 100 ], [ 'red', 2, 1 ],
[ 'red', 2, 10 ], [ 'red', 2, 100 ],
[ 'green', 1, 1 ], [ 'green', 1, 10 ],
[ 'green', 1, 100 ], [ 'green', 2, 1 ],
[ 'green', 2, 10 ], [ 'green', 2, 100 ],
[ 'blue', 1, 1 ], [ 'blue', 1, 10 ],
[ 'blue', 1, 100 ], [ 'blue', 2, 1 ],
[ 'blue', 2, 10 ], [ 'blue', 2, 100 ]
]
However, my goal is to have the output type as [Color, number, Size][]
, rather than any[][]
.
I believe the solution lies in utilizing a variadic generic type effectively, but I am unable to figure it out at the moment.