TypeScript构建Promise.all类似函数-重载签名与函数实现不兼容

时间:2019-04-20 22:17:34

标签: typescript

通过使用TypeScript,使用sequentially的任何人都应被强制将1传递给N个参数,该参数的输入Promise<T>等于输出[Promise<T>,..

[不起作用] ,按以下方式重载时,我在第一个声明中遇到tslint错误:

  

重载签名与函数实现不兼容。 ts(2394)

promise.ts

function sequentially<T1>(promiseWrappers: [
  () => Promise<T1>
]): Promise<[T1]>;
async function sequentially<T1, T2>(promiseWrappers: [
  () => Promise<T1>,
  () => Promise<T2> 
]): Promise<[T1, T2]> {
  const resolved = [];
  for (const wrapper of promiseWrappers) {
    resolved.push(await wrapper());
  }
  // @ts-ignore
  return resolved;
}

[工作中] 似乎唯一可行的方法是使用.js和单独的声明文件.d.ts编写实现,如下所示:

promise.js

export async function sequentially(promiseWrappers) {
  const resolved = [];
  for (const wrapper of promiseWrappers) {
    resolved.push(await wrapper());
  }
  return resolved;
}

promise.d.ts

export declare function sequentially<T1, T2>(promiseWrappers: [
  () => Promise<T1>,
  () => Promise<T2>
]): Promise<[T1, T2]>;

export declare function sequentially<T1, T2, T3>(promiseWrappers: [
  () => Promise<T1>,
  () => Promise<T2>,
  () => Promise<T3>
]): Promise<[T1, T2, T3]>;

如何解决第一个TS实施案例?

2 个答案:

答案 0 :(得分:2)

您可能希望支持的重载可能与彼此无关。为此,请使最底部的签名成为所有any类型。这样的事情应该适合您。

function sequentially<T1>(promiseWrappers: [
  () => Promise<T1>
]): Promise<[T1]>;
function sequentially<T1, T2>(promiseWrappers: [
  () => Promise<T1>,
  () => Promise<T2> 
]): Promise<[T1, T2]>;
async function sequentially(promiseWrappers: any[]): Promise<any[]> {
  const resolved = [];
  for (const wrapper of promiseWrappers) {
    resolved.push(await wrapper());
  }
  // @ts-ignore
  return resolved;
}

答案 1 :(得分:2)

在TypeScript中有一些实现重载函数的规则:

  1. 调用站点未考虑实现签名,它仅用于对实现进行类型检查(在overloads in the handbook文档末尾提到)

  2. 实现签名必须具有与所有重载签名声明兼容的参数。实际上,这意味着每种参数类型都必须是该参数位置的所有重载中所有参数类型的并集类型。

  3. 实现签名必须具有返回类型,该类型是所有重载的返回类型的交集。实际上,这意味着实现必须在每个return语句中将类型强制转换为该类型,或者只是将实现返回类型声明为any。

我在任何地方都找不到2和3的文档,但是它们遵循通用的差异规则,以实现函数类型的兼容性以及实现签名必须与所有重载声明兼容的事实。

下面是代码,它们在--strictFunctionTypes--noImplicitAny打开的情况下进行编译

function sequentially<T1>(promiseWrappers: [
    () => Promise<T1>
]): Promise<[T1]>;
function sequentially<T1, T2>(promiseWrappers: [
    () => Promise<T1>,
    () => Promise<T2>,
]): Promise<[T1, T2]>;
async function sequentially<T1, T2>(promiseWrappers: [
  () => Promise<T1>,
] | [
  () => Promise<T1>,
  () => Promise<T2> 
]): Promise<[T1, T2] & [T1]> {
  const resolved = [] as unknown as [T1, T2] & [T1];
  for (const wrapper of promiseWrappers) {
    resolved.push(await wrapper());
  }
  return resolved;
}