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[]
.