我有苹果和梨——它们都有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];

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

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

不幸的是,Typescript告诉我:

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不喜欢 fresh 水果,还是这是一个Typescript错误?

You can try it yourself in the official Typescript Repl.

推荐答案

TypeScript支持 struct 类型(也称为duck类型),这意味着types are compatible when they share the same members.你的问题是ApplePear没有共享所有成员,这意味着它们不兼容.然而,它们与另一种只有isDecayed: boolean个成员的类型兼容.由于 struct 类型,您不需要从这样的接口继承ApplePear.

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

Assign type during variable declaration

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

const fruits = fruitBasket[key];

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

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

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

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

Cast to compatible type for the operation

给定解决方案的问题在于它改变了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[]型.

Typescript相关问答推荐

为什么文字必须硬编码才能在TypScript中工作?

TS 2339:属性切片不存在于类型DeliverableSignal产品[]上>'

我们过go 不能从TypeScript中的联合中同时访问所有属性?

如何访问Content UI的DatePicker/中的sx props of year picker?'<>

学习Angular :无法读取未定义的属性(正在读取推送)

访问继承接口的属性时在html中出错.角形

了解类型规则中的关键字

有没有可能为这样的函数写一个类型?

Vue3 Uncaught SyntaxError:每当我重新加载页面时,浏览器控制台中会出现无效或意外的令牌

FatalError:Error TS6046:';--模块分辨率';选项的参数必须是:'; node ';,'; node 16';,'; node

基元类型按引用传递的解决方法

确保对象列表在编译时在类型脚本中具有唯一键

创建Angular 为17的动态形状时出错

基于泛型的条件接口键

如何将类似数组的对象(字符串::匹配结果)转换为类型脚本中的数组?

可以用任意类型实例化,该类型可能与

可以将JS文件放在tsconfig';s includes/files属性?或者,我如何让tsc判断TS项目中的JS文件?

在tabel管理区域react js上设置特定顺序

如何创建允许使用带有联合类型参数的Array.from()的TS函数?

将带有额外id属性的Rust struct 展平回TypeScript单个对象,以返回wasm-bindgen函数