首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >无法调用其类型缺少调用签名的表达式

无法调用其类型缺少调用签名的表达式
EN

Stack Overflow用户
提问于 2017-02-24 06:27:27
回答 4查看 131.8K关注 0票数 78

我有苹果和梨-它们都有一个isDecayed属性:

代码语言:javascript
复制
interface Apple {
    color: string;
    isDecayed: boolean;
}

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

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

代码语言:javascript
复制
interface FruitBasket {
   apples: Apple[];
   pears: Pear[];
}

现在让我们假设我的篮子是空的:

代码语言:javascript
复制
const fruitBasket: FruitBasket = { apples: [], pears: [] };

现在我们从篮子里随机拿出一种:

代码语言:javascript
复制
const key: keyof FruitBasket = Math.random() > 0.5 ? 'apples': 'pears'; 
const fruits = fruitBasket[key];

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

代码语言:javascript
复制
const freshFruits = fruits.filter((fruit) => !fruit.isDecayed);

不幸的是Typescript告诉我:

无法调用其类型缺少调用签名的表达式。类型'((callbackfn:(value: Apple,index: number,array: Apple[]) => any,thisArg?:any) => Apple[]) | ...‘没有兼容的调用签名。

这是怎么回事--只是Typescript不喜欢新鲜水果,还是这是一个Typescript bug?

您可以在官方Typescript Repl中亲自体验。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2017-02-27 21:33:43

TypeScript支持结构化类型(也称为鸭子类型),这意味着types are compatible when they share the same members。您的问题是ApplePear不共享所有成员,这意味着它们不兼容。但是,它们与只有isDecayed: boolean成员的另一种类型兼容。由于结构类型,您不需要从这样的接口继承ApplePear

有不同的方法可以指定这样的兼容类型:

变量声明期间的赋值类型

此语句隐式类型化为Apple[] | Pear[]

代码语言:javascript
复制
const fruits = fruitBasket[key];

您只需在变量声明中显式使用兼容类型:

代码语言:javascript
复制
const fruits: { isDecayed: boolean }[] = fruitBasket[key];

为了增加可重用性,您还可以先定义类型,然后在声明中使用它(请注意,不需要更改ApplePear接口):

代码语言:javascript
复制
type Fruit = { isDecayed: boolean };
const fruits: Fruit[] = fruitBasket[key];

对于操作强制转换为兼容类型

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

代码语言:javascript
复制
const fruits: fruitBasket[key];
const freshFruits = (fruits as { isDecayed: boolean }[]).filter(fruit => !fruit.isDecayed) as typeof fruits;

或者使用可重用的Fruit类型:

代码语言:javascript
复制
type Fruit = { isDecayed: boolean };
const fruits: fruitBasket[key];
const freshFruits = (fruits as Fruit[]).filter(fruit => !fruit.isDecayed) as typeof fruits;

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

票数 90
EN

Stack Overflow用户

发布于 2017-02-24 06:50:28

正如在评论中@peter最初链接的github issue中所提到的:

代码语言:javascript
复制
const freshFruits = (fruits as (Apple | Pear)[]).filter((fruit: (Apple | Pear)) => !fruit.isDecayed);
票数 7
EN

Stack Overflow用户

发布于 2017-02-24 06:35:51

也许可以创建一个提供isDecayed的共享Fruit接口。fruits现在的类型是Fruit[],因此该类型可以是显式的。如下所示:

代码语言:javascript
复制
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);
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42427393

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档