打字稿异步/等待无法确定正确的返回类型

时间:2020-05-11 10:03:03

标签: typescript asynchronous mongoose async-await

我在打字稿中有以下基于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);
    });
}

该方法基本上基于另一个查询的结果向(猫鼬)聚合添加了过滤器。

这很好用,打字稿很高兴。

问题

如果我尝试将其转换为使用异步/等待模式,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);
}

这次,我从return ...行的Typescript中收到编译错误,告诉我:

TS2322:类型“ any []”不可分配给类型“ Aggregate <任何[]>”

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

因此,该问题似乎是由Aggregate提供的mongoose类型特有的。

Here's a reproduction of the issue

1 个答案:

答案 0 :(得分:0)

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

我浏览了mongoose implementation of the Aggregate class,他们已经将thencatch函数添加到Aggregate类中,以使其表现出应有的作用。这将使异步/等待操作符将其视为承诺,因为他们将具有then函数的任何对象视为承诺。这就是Aggregate类从异步方法返回时似乎解开的原因。

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