TypeScript中的async/await无法确定正确的返回类型。

3

我有以下基于Promise的TypeScript方法:

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

这个方法基本上是在(mongoose)聚合中添加一个过滤器,基于另一个查询的结果。

这个方法完全正常,而且Typescript很高兴。

问题

如果我尝试将其转换为使用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 []”不可分配给类型“Aggregate< any[]>”

似乎Typescript无法从query.match(matcher)函数中推断出正确的返回类型,即使将其转换为as Aggregate<any[]>也没有帮助。

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

我正在使用Typescript版本3.7.2

有人能解释一下为什么会发生这种情况,以及是否有解决方法可以在仍然能够使用async/await的情况下进行 - 而不必将代码的部分包装在promise中吗?我感觉自己已经尝试了每种类型的显式强制转换,但迄今为止都没有运气。

更新1

我将有问题的代码简化为:

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

尽管这个示例基本上什么也没做,但它仍然会引起编译错误。由于某种原因,async 关键字似乎只是解开了 Aggregate 类型。

与之相比,以下代码类似,但不会导致错误:

declare class SomeGenericClass<T> {}

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

看起来问题与mongoose提供的Aggregate类型有关。

这里是该问题的演示


1
可能与您使用 any 有关。它会完全破坏类型检查链。由于查询本身具有 any,因此在使用 query.match 时无法评估类型。这只是一种假设。如果您在 TypeScript playground 上提供最小可重现代码,那将更好。 - Eugene Obrezkov
我尝试用显式类型替换任何类型,但是我只得到了错误Type 'SomeDocument[]' is not assignable to type 'Aggregate<SomeDocument[]>'。我会尝试在在线游乐场中重现它。 - Nikolaj Dam Larsen
1
findSomething 是如何定义的?提供一个可重现的示例会很有帮助。 - Aleksey L.
“findSomething” 方法似乎与此无关。我还没有在沙盒环境中复现这个问题。 - Nikolaj Dam Larsen
我也尝试复现这个问题,但它完美地工作了,即使使用了从https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/mongoose/index.d.ts中声明的Aggregate。 - Aluan Haddad
显示剩余2条评论
1个回答

0

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

我查看了mongoose实现的Aggregate,他们添加了thencatch函数到Aggregate类中,使其像一个promise一样运行。这将使async/await操作符将其视为promise,因为它们将任何具有then函数的对象视为promise。这就是为什么Aggregate类似乎在从异步方法返回时被解包的原因。

对于手头的具体问题,作为一种解决方法,我只是将方法的异步部分移回到调用代码中。基本上就像我开始尝试之前那样。它并不完美,但它能工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接