我在 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
类的猫鼬实现,他们添加了then
和catch
函数到 Aggregate 类中,使其像一个承诺。这将使 async/await 运算符将其视为承诺,因为它们将任何具有then
-函数的对象视为承诺。这就是Aggregate
-class 在从异步方法返回时似乎解包的原因。
对于手头的特定问题,作为解决方法,我只是将方法的异步部分移回调用代码。基本上就像我开始修补它之前一样。它并不完美,但它有效。