我正在尝试为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'.
答案 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。其中包含一些模拟的接口/类型,但我相信您会明白这一点的。