如何返回链接的异步函数的结果?

问题描述 投票:0回答:1

使用打字稿3.7。

鉴于此处定义的命令和命令处理程序的标准概念,该处理程序可能是异步的:

export type Command = { name: string; body: any };
export type CommandHandler<TCommand extends Command, TResult = any> = (cmd: TCommand) => TResult | Promise<TResult>;

我正在尝试创建一个函数,给定一个命令处理程序数组,该函数将返回一个新的命令处理程序,该命令处理程序有效地调用每个处理程序顺序地并返回最后执行的处理程序的结果,从而允许任何处理程序中断处理程序链。

我希望这样的事情可以工作:

export const chain = <TCommand extends Command, TResult = any>(
  ...handlers: CommandHandler<TCommand, TResult>[]
): CommandHandler<TCommand, TResult> => async cmd => {
  let result: TResult;
  for (const handler of handlers) {
    result = await handler(cmd);
  }

  return result;
};

但是编译器给我这个错误:Variable 'result' is used before being assigned. ts(2454)

为什么不起作用,如何组织该代码?

typescript
1个回答
0
投票

如果handlers为空,TypeScript将此理解为let result: TResult; return result,它返回undefinedany是垃圾,effectively disables TypeScript

TypeScript在无法确定表达式的类型时会使用类型any。与Dynamic相比,将any称为类型是一种高估。不管它出现在哪里,它都会关闭类型检查器。

考虑此替代方法-

type Command<T> =
  { name: string; body: T | void }

type CommandHandler<T> =
  (cmd: Command<T>) => Promise<T | void>

function chain <T>(...handlers: Array<CommandHandler<T>>): CommandHandler<T>
{ return async (cmd: Command<T>): Promise<T | void> =>
  { let r
    for (const h of handlers)
      r = await h(cmd)
    return r
  }
}

因为我们将chain的返回类型定义为CommandHandler<T>,所以我们甚至不需要async函数周围的额外类型提示-

type Command<T> =
  { name: string; body: T | void }

type CommandHandler<T> =
  (cmd: Command<T>) => Promise<T | void>

function chain <T>(...handlers: Array<CommandHandler<T>>): CommandHandler<T>
{ return async cmd =>  // <-- cmd inferred as Command<T>
  { let r
    for (const h of handlers)
      r = await h(cmd)
    return r // <-- inferred T | void
  }
}

演示:验证此typescript sandbox中的结果

热门问题
推荐问题
最新问题