Estoy tratando de reduce
una unión de tipos de matriz: foo[] | bar[]
. Con map
funciona como se esperaba y obtengo un elemento de foo|bar
en el lamda, pero no funciona con reduce
. Recibo el error de que 'la expresión no se puede llamar, porque las firmas no son compatibles'.
Tal vez esto esté relacionado, pero eso fue en TS 3.6 días y estoy usando 4.5. ¿Hay una forma (limpia) de evitar esto?
Tengo un patio de juegos mecanografiado aquí
const m = [] as Array<number | string>; m.reduce((it) => it); // ok m.map((it) => it); // ok const m2 = [] as Array<number> | Array<string>; m2.reduce((it) => it); m2.reduce((it) => it as any); // not even with 'any'-lambda // This expression is not callable. // Each member of the union type '<OMITTED> ...' has signatures, but none of those signatures are compatible with each other. m2.map((it) => it); // why does `map` work then ? // same with tuples const m3 = [1, 1] as [number, number] | [string]; m3.map((it) => it); m3.reduce((it) => it); // same error
Además del comentario de jcalz, encontré lo siguiente.
La firma de la función para el mapa es
export function map<T, U>(iterable: Iterable<T>, mapper: (value: T, index: number, iterable: Iterable<T>) => U): U[];
Tiene un tipo de retorno U diferente a la entrada T.
Una de las firmas de función para reducir es
export function reduce<T>( iterable: Iterable<T>, reducer: (previousValue: T, currentValue: T, currentIndex: number, iterable: Iterable<T>) => T, initialValue?: T ): T;
Tiene el mismo tipo de retorno que su entrada (T). El problema surge cuando se vuelve a asignar el tipo a sí mismo. Typescript no sabe (y no debería) saber qué tipo usar.
Una solución es verificar el tipo antes de usar reduce, con una protección de tipo como esta,
const isNumberArray = (arr: unknown[]): arr is number[] => { for (let i = 0; i < arr.length; i++) { const element = arr[i] if (typeof element !== 'number') { return false } } return true }