Typescript async/await 无法确定正确的返回类型



我在 Typescript 中有以下基于 Promise 的方法:

filterByParams(
query: Aggregate<any[]>,
params: ParamsObject
): Promise<Aggregate<any[]>> {
return this.findSomething(params)
.then<Aggregate<any[]>>((results: SomeResultType[]) => {
const matcher = {
// ... using results to match something
};
return query.match(matcher);
});
}

该方法基本上根据另一个查询的结果将筛选器添加到(猫鼬(聚合中。

这工作得很好,打字稿很高兴。

问题

如果我尝试将其转换为使用 async/await 模式,Typescript 开始抱怨。这是转换后的方法:

async filterByParams(
query: Aggregate<any[]>,
params: ParamsObject
): Promise<Aggregate<any[]>> {
const results: SomeResultType[] = await this.findSomething(params);
const matcher = {
// ... using results to match something
};
return query.match(matcher);
}

这次我从 Typescript 收到一个编译错误,在return ...行上,告诉我:

TS2322:类型"any[]"不可分配给类型"聚合<任何[]>

似乎 Typescript 无法从query.match(matcher)函数推断出正确的返回类型,甚至将其转换为as Aggregate<any[]>也无济于事。

如果我从基于 Promise 的方法中的then(..)函数中删除泛型类型,则会出现与使用 async/await 语法时大致相同的错误。

我正在使用打字稿版本 3.7.2

谁能解释为什么会发生这种情况,以及是否有一种解决方法,我仍然可以使用 async/await - 而无需将部分代码包装在承诺中?我觉得我已经尝试过明确地铸造每种类型,但到目前为止没有运气。

更新 1

我已经将有问题的代码减少到这个:

async filterByParams(
query: Aggregate<any[]>
) {
return query;
}

虽然此示例基本上什么都不做,但它仍然会导致编译错误。出于某种原因,async关键字似乎只是解开了Aggregate类型。

将此代码与以下代码进行比较,后者类似,但不会导致错误:

declare class SomeGenericClass<T> {}
async filterByParams(
query: SomeGenericClass<any[]>
) {
return query;
}

因此,该问题似乎在某种程度上特定于mongoose提供的Aggregate类型。

这是问题的重现

虽然我没有找到确切的解决方案,但我找到了解释。

我已经浏览了Aggregate类的猫鼬实现,他们添加了thencatch函数到 Aggregate 类中,使其像一个承诺。这将使 async/await 运算符将其视为承诺,因为它们将任何具有then-函数的对象视为承诺。这就是Aggregate-class 在从异步方法返回时似乎解包的原因。

对于手头的特定问题,作为解决方法,我只是将方法的异步部分移回调用代码。基本上就像我开始修补它之前一样。它并不完美,但它有效。