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

我有苹果和梨——两者都有 isDecayed属性:

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


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

而且这两种类型都可以在我的水果篮里(多次) :

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

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

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

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

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

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

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

不幸的是,打字稿告诉我:

无法调用其类型缺乏调用签名的表达式。键入’((callbackfn: (value: Apple,index: number,array: Apple []) = > any,this Arg?: any) = > Apple [] | ...’没有兼容的呼叫签名。

这里出了什么问题-只是打字机不喜欢新鲜水果或这是一个打字机错误?

你可以在官方的 打字稿代表中自己试试。

139942 次浏览

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

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);

正如@peter 在评论中最初链接的 Github 的问题中提到的:

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

TypeScript 支持结构化类型(也称为 Duck 类型) ,这意味着 当它们共享相同的成员时,类型是兼容的。您的问题是 ApplePear不共享它们的所有成员,这意味着它们不兼容。但是,它们与只有 isDecayed: boolean成员的另一种类型兼容。由于结构类型的原因,您不需要从这样的接口继承 ApplePear

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

在变量声明期间分配类型

此语句隐式输入到 Apple[] | Pear[]:

const fruits = fruitBasket[key];

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

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

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

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

强制转换为操作的兼容类型

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

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

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

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

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

我对数字有同样的问题,一个 JS 库。修复方法是使用以下命令再次安装输入:

npm install --save @types/numeral