将通用变量传递给嵌套函数

时间:2018-12-27 17:24:45

标签: typescript typescript-typings

我正在尝试为express.js的“异步路由”包装编写类型定义。我是TypeScript的新手,刚刚了解了泛型。

由于可以在扩展默认快递Request的中间件后面调用该函数,因此我想创建它,以便用户可以提供自己的扩展“请求”。

到目前为止,我已经:

asyncRoute.ts

import { NextFunction } from 'express';

type Fn = <R, S>(req: R, res: S, next?: NextFunction) => Promise<any>;

export default function asyncRoute<R, S> (fn: Fn) {
  return function asyncRouteWrap(req: R, res: S, next: NextFunction) {
    Promise.resolve(fn<R,S>(req, res, next)).catch(next);
  };
};

用法:

import { Request } from 'express';

interface AppRequest extends Request {
  log: Logger;
  // ...other stuff
}

router.get(
  '/',
  asyncRoute<AppRequest, AppResponse>(async (req, res) => {
    req.log.info('test');
  })
);

但是我得到Property 'log' does not exist on type 'Request'.

1 个答案:

答案 0 :(得分:2)

问题在于TypeScript编译器无法在req的匿名函数参数中推断asyncRouter的类型。如果您具有对TypeScript的IDE支持,则会看到fn<R, S>(req, res, next)并没有绑定到R的{​​{1}}(在VS Code中,您只需将鼠标悬停在特定的代码行上)。

您可以通过在AppRequest的定义中向Fn显式添加类型参数来解决问题。为此,您需要首先将类型参数添加到asyncRoute

的类型定义中
Fn

然后按如下所示定义type Fn<R, S> = (req: R, res: S, next?: NextFunction) => Promise<any>

asyncRoute

现在应该消除类型错误。


这是一个带有完整代码的Typescript Playground。其中包含一些模拟的接口/类型,但我相信您会明白这一点的。