type tutorial multiple initialize array javascript typescript types

javascript - tutorial - No se puede invocar una expresión cuyo tipo carece de una firma de llamada



typescript object type (4)

Como se menciona en el github.com/Microsoft/TypeScript/issues/7960 originalmente vinculado por @peter en los comentarios:

const freshFruits = (fruits as (Apple | Pear)[]).filter((fruit: (Apple | Pear)) => !fruit.isDecayed);

Tengo manzana y peras, ambas tienen un atributo isDecayed :

interface Apple { color: string; isDecayed: boolean; } interface Pear { weight: number; isDecayed: boolean; }

Y ambos tipos pueden estar en mi cesta de frutas (varias veces):

interface FruitBasket { apples: Apple[]; pears: Pear[]; }

Supongamos por ahora que mi cesta está vacía:

const fruitBasket: FruitBasket = { apples: [], pears: [] };

Ahora sacamos al azar un tipo de la cesta:

const key: keyof FruitBasket = Math.random() > 0.5 ? ''apples'': ''pears''; const fruits = fruitBasket[key];

Y, por supuesto, a nadie le gustan las frutas en descomposición, por lo que elegimos solo las frescas:

const freshFruits = fruits.filter((fruit) => !fruit.isDecayed);

Lamentablemente mecanografiado me dice:

No se puede invocar una expresión cuyo tipo carece de una firma de llamada. Escriba ''((callbackfn: (valor: Apple, index: number, array: Apple []) => any, thisArg ?: any) => Apple []) | ... ''no tiene firmas de llamada compatibles.

¿Qué hay de malo aquí? ¿Es solo que a Typecript no le gustan las frutas frescas o es un error de Typecript?

Puede probarlo usted mismo en la respuesta oficial de mecanografía .


Quizás cree una interfaz compartida de Fruit que proporcione isDecayed. Fruit[] ahora es de tipo Fruit[] por lo que el tipo puede ser explícito. Me gusta esto:

interface Fruit { isDecayed: boolean; } interface Apple extends Fruit { color: string; } interface Pear extends Fruit { weight: number; } interface FruitBasket { apples: Apple[]; pears: Pear[]; } const fruitBasket: FruitBasket = { apples: [], pears: [] }; const key: keyof FruitBasket = Math.random() > 0.5 ? ''apples'': ''pears''; const fruits: Fruit[] = fruitBasket[key]; const freshFruits = fruits.filter((fruit) => !fruit.isDecayed);


Tuve el mismo problema con numeral, una biblioteca JS. La solución fue instalar los tipings nuevamente con este comando:

npm install --save @types/numeral


TypeScript admite la tipificación estructural (también denominada tipificación de pato), lo que significa que los tipos son compatibles cuando comparten los mismos miembros . Su problema es que Apple y Pear no comparten todos sus miembros, lo que significa que no son compatibles. Sin embargo, son compatibles con otro tipo que solo tiene isDecayed: boolean member. Debido a la tipificación estructural, no necesita heredar Apple y Pear de dicha interfaz.

Hay diferentes formas de asignar un tipo tan compatible:

Asignar tipo durante la declaración de variable

Esta declaración está implícitamente escrita en Apple[] | Pear[] Apple[] | Pear[] :

const fruits = fruitBasket[key];

Simplemente puede usar un tipo compatible explícitamente en su declaración de variable:

const fruits: { isDecayed: boolean }[] = fruitBasket[key];

Para una reutilización adicional, también puede definir primero el tipo y luego usarlo en su declaración (tenga en cuenta que las interfaces de Apple y Pear no necesitan ser cambiadas):

type Fruit = { isDecayed: boolean }; const fruits: Fruit[] = fruitBasket[key];

Fundido a tipo compatible para la operación

El problema con la solución dada es que cambia el tipo de la variable de fruits . Esto podría no ser lo que quieres. Para evitar esto, puede reducir la matriz a un tipo compatible antes de la operación y luego volver a establecer el tipo al mismo tipo que las fruits :

const fruits: fruitBasket[key]; const freshFruits = (fruits as { isDecayed: boolean }[]).filter(fruit => !fruit.isDecayed) as typeof fruits;

O con el tipo de Fruit reutilizable:

type Fruit = { isDecayed: boolean }; const fruits: fruitBasket[key]; const freshFruits = (fruits as Fruit[]).filter(fruit => !fruit.isDecayed) as typeof fruits;

La ventaja de esta solución es que tanto las fruits como las fruits freshFruits serán del tipo Apple[] | Pear[] Apple[] | Pear[] .