无法调用类型缺少调用签名的表达式 [英] Cannot invoke an expression whose type lacks a call signature

查看:81
本文介绍了无法调用类型缺少调用签名的表达式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有苹果和梨-都具有isDecayed属性:

I have apple and pears - both have an isDecayed attribute:

interface Apple {
    color: string;
    isDecayed: boolean;
}

interface Pear {
    weight: number;
    isDecayed: boolean;
}

这两种类型都可以放在我的水果篮中(多次):

And both types can be in my fruit basket (multiple times):

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

让我们暂时假设我的购物篮是空的:

Let's assume for now my basket is empty:

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

现在,我们从篮子中随机抽取一种:

Now we take randomly one kind out of the basket:

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

当然没有人喜欢腐烂的水果,所以我们只选择新鲜的水果:

And of course nobody likes decayed fruits so we pick only the fresh ones:

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

不幸的是打字稿告诉我:

Unfortunately Typescript tells me:

无法调用类型缺少调用签名的表达式.类型'(((callbackfn:(值:苹果,索引:数字,数组:苹果[])=>任何,thisArg ?:任何)=>苹果[])| ..."没有兼容的呼叫签名.

Cannot invoke an expression whose type lacks a call signature. Type '((callbackfn: (value: Apple, index: number, array: Apple[]) => any, thisArg?: any) => Apple[]) | ...' has no compatible call signatures.

这是怎么回事-仅仅是Typescript不喜欢新鲜水果还是这是Typescript错误?

What's wrong here - is it just that Typescript doesn't like fresh fruits or is this a Typescript bug?

您可以在官方推荐答案

TypeScript支持结构化类型化(也称为鸭子类型化),这意味着

TypeScript supports structural typing (also called duck typing), meaning that types are compatible when they share the same members. Your problem is that Apple and Pear don't share all their members, which means that they are not compatible. They are however compatible to another type that has only the isDecayed: boolean member. Because of structural typing, you don' need to inherit Apple and Pear from such an interface.

分配这种兼容类型的方法有多种:

There are different ways to assign such a compatible type:

在变量声明期间分配类型

此语句隐式键入为Apple[] | Pear[]:

const fruits = fruitBasket[key];

您可以简单地在变量声明中显式使用兼容类型:

You can simply use a compatible type explicitly in in your variable declaration:

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

为了获得更高的可重用性,您还可以先定义类型,然后在声明中使用它(请注意,无需更改ApplePear接口):

For additional reusability, you can also define the type first and then use it in your declaration (note that the Apple and Pear interfaces don't need to be changed):

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

将该操作转换为兼容类型

给定解决方案的问题在于它更改了fruits变量的类型.这可能不是您想要的.为避免这种情况,您可以在操作前将数组缩小为兼容的类型,然后将其设置回与fruits相同的类型:

The problem with the given solution is that it changes the type of the fruits variable. This might not be what you want. To avoid this, you can narrow the array down to a compatible type before the operation and then set the type back to the same type as fruits:

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

或具有可重复使用的Fruit类型:

Or with the reusable Fruit type:

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

此解决方案的优点是fruitsfreshFruits都将是Apple[] | Pear[]类型.

The advantage of this solution is that both, fruits and freshFruits will be of type Apple[] | Pear[].

这篇关于无法调用类型缺少调用签名的表达式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆