Aquí está la firma de tipo que busco:
function cartesianProduct<T1, T2, T3, T4, T5, T6, T7, T8>([c1, c2, c3, c4, c5, c6, c7, c8]: [T1[], T2[], T3[], T4[], T5[], T6[], T7[], T8[]]): [T1, T2, T3, T4, T5, T6, T7, T8][]; function cartesianProduct<T1, T2, T3, T4, T5, T6, T7>([c1, c2, c3, c4, c5, c6, c7]: [T1[], T2[], T3[], T4[], T5[], T6[], T7[]]): [T1, T2, T3, T4, T5, T6, T7][]; function cartesianProduct<T1, T2, T3, T4, T5, T6>([c1, c2, c3, c4, c5, c6]: [T1[], T2[], T3[], T4[], T5[], T6[]]): [T1, T2, T3, T4, T5, T6][]; function cartesianProduct<T1, T2, T3, T4, T5>([c1, c2, c3, c4, c5]: [T1[], T2[], T3[], T4[], T5]): [T1, T2, T3, T4, T5][]; function cartesianProduct<T1, T2, T3, T4>([c1, c2, c3, c4]: [T1[], T2[], T3[], T4[]]): [T1, T2, T3, T4][]; function cartesianProduct<T1, T2, T3>([c1, c2, c3]: [T1[], T2[], T3[]]): [T1, T2, T3][]; function cartesianProduct<T1, T2>([c1, c2]: [T1[], T2[]]): [T1, T2][]; function cartesianProduct<T>(sets: T[][]): T[][] { // implementation }Aquí hay un ejemplo de lo que espero que haga. Dado:
const input = [ [ 'a', 'b' ], [ 1, 2 ], ];Escupiría:
const output = [ [ 'a', 1 ], [ 'a', 2 ], [ 'b', 1 ], [ 'b', 2 ], ];Intentar utilizar esta implementación de referencia nos da este tipo de problema:
Aquí hay un parque infantil .
Si desea utilizar Ramda, puede utilizar R.sequence con matrices.
const cartesianProduct = R.sequence(Array.of) const input = [ [ 'a', 'b' ], [ 1, 2 ], ]; cartesianProduct(input) //=> [["a", 1], ["a", 2], ["b", 1], ["b", 2]]Para problemas como estos, siempre me gusta comenzar primero con los tipos.
Primero un tipo para extraer el tipo de elemento de una matriz:
type ElementType<A> = A extends ReadonlyArray<infer T> ? T : never; Sí, sé que A[number] existe, pero esto dará como resultado errores de tipo más adelante porque A será un resultado de infer .
Luego, un tipo que toma una lista de arreglos y nos da sus tipos de elementos.
type ElementsOfAll<Inputs, R extends ReadonlyArray<unknown> = []> = Inputs extends readonly [infer F, ...infer M] ? ElementsOfAll<M, [...R, ElementType<F>]> : R; Es casi como Inputs.map((F) => ElementType(F)) en el código.
Finalmente usamos este tipo para definir un tipo de producto cartesiano:
type CartesianProduct<Inputs> = ElementsOfAll<Inputs>[];Ahora que lo hicimos en tipos, es hora de hacerlo en código:
function cartesianProduct(sets) { return sets.reduce((a, b) => a.flatMap(d => b.map(e => [d, e].flat()))); } Esta increíble implementación se tomó de esta excelente respuesta donde puede encontrar otras alternativas si su entorno no es compatible flat o flatMap .
Después de tener esta implementación, agregamos los tipos:
function cartesianProduct<Sets extends ReadonlyArray<ReadonlyArray<unknown>>>(sets: Sets): CartesianProduct<Sets> { return sets.reduce((a, b) => a.flatMap(d => b.map(e => [d, e].flat()))); } Pero hay un error porque el tipo de devolución no coincide con el tipo de llamada de reduce . Desafortunadamente, no conozco una buena manera de eliminar el error, pero si un lanzamiento es aceptable:
function cartesianProduct<Sets extends ReadonlyArray<ReadonlyArray<unknown>>>(sets: Sets): CartesianProduct<Sets> { return sets.reduce((a, b) => a.flatMap(d => b.map(e => [d, e].flat()))) as CartesianProduct<Sets>; }