TypeScript: вызов перегруженного asyncPipe с 0 или более аргументами. - PullRequest
2 голосов
/ 27 февраля 2020

У меня есть asyncPipe функция, подобная этой:

export function asyncPipe<A, B>(
  ab: (a: A) => MaybePromise<B>
): (a: MaybePromise<A>) => Promise<B>;
export function asyncPipe<A, B, C>(
  ab: (a: A) => MaybePromise<B>,
  bc: (b: B) => MaybePromise<C>
): (a: MaybePromise<A>) => Promise<C>;
export function asyncPipe<A, B, C, D>(
  ab: (a: A) => MaybePromise<B>,
  bc: (b: B) => MaybePromise<C>,
  cd: (c: C) => MaybePromise<D>
): (a: MaybePromise<A>) => Promise<D>;
export function asyncPipe<A, B, C, D, E>(
  ab: (a: A) => MaybePromise<B>,
  bc: (b: B) => MaybePromise<C>,
  cd: (c: C) => MaybePromise<D>,
  de: (d: D) => MaybePromise<E>
): (a: MaybePromise<A>) => Promise<E>;

export function asyncPipe(...fns: Function[]) {
  return (x: any) => fns.reduce(async (y, fn) => fn(await y), x);
}

Я хочу назвать это так:

const createRoute = (...middleware: any[]) => async (
  request: any,
  response: any
) => {
  try {
    await asyncPipe(...middleware)({
      request,
      response
    });
  } catch (e) {
    console.error(e);
    response.status(500);
    response.json({
      error: "Internal Server Error"
    });
  }
};

TypeScript жалуется и говорит Expected 1-6 arguments, but got 0 or more. в строке в который я называю asyncPipe. Как я могу сказать, что middleWare всегда будет хотя бы одним аргументом или перегружать его, поэтому он также принимает 0 аргументов?

Обновление:

Я попробовал ответ Роба так:

export function asyncPipe<A>(...fns: Function[]): MaybePromise<A>;

Но это предотвращает провал всех моих asyncPipe специфических c тестов. Кстати, тесты выглядят так:

import { describe } from "riteway";

import { asyncPipe } from "./asyncPipe";

const asyncInc = (n: number) => Promise.resolve(n + 1);
const inc = (n: number) => n + 1;

describe("asyncPipe()", async assert => {
  assert({
    given: "a promise",
    should: "pipe it",
    actual: await asyncPipe(asyncInc)(1),
    expected: 2
  });

  assert({
    given: "two promises",
    should: "pipe them",
    actual: await asyncPipe(asyncInc, asyncInc)(1),
    expected: 3
  });

  assert({
    given: "three promises",
    should: "pipe them",
    actual: await asyncPipe(asyncInc, asyncInc, asyncInc)(1),
    expected: 4
  });

  assert({
    given: "promises mixed with synchronous function",
    should: "pipe them",
    actual: await asyncPipe(asyncInc, inc, asyncInc)(1),
    expected: 4
  });

  {
    const throwInc = (n: number) => Promise.reject(n + 1);

    assert({
      given: "promises where one throws",
      should: "pipe them",
      actual: await asyncPipe(asyncInc, throwInc, asyncInc)(1).catch(x => x),
      expected: 3
    });
  }
});

1 Ответ

1 голос
/ 27 февраля 2020

Добавить определение «ноль или более». Например, вы можете предоставить определение вашей реализации:

// Previous definitions
export function asyncPipe(...fns: Function[]);

export function asyncPipe(...fns: Function[]) {
  return (x: any) => fns.reduce(async (y, fn) => fn(await y), x);
}
...