Typescript - 创建自定义快速中间件定义
Posted
技术标签:
【中文标题】Typescript - 创建自定义快速中间件定义【英文标题】:Typescript - Creating custom express middleware definition 【发布时间】:2020-02-05 07:00:58 【问题描述】:我一直在为我们的应用定义自定义中间件时遇到困难。我正在使用 typescript@3.6.3 和 express@4.17.1。
我看到的所有键入中间件的示例都暗示用户没有向req
或res
参数添加任何内容,但我知道这是中间件的重点——改变其中任何一个那些知道必须以特定顺序加载中间件的对象(即,cookie-parser 或 body-parser 在早期就因此而臭名昭著,我猜现在仍然如此?)。无论如何,大多数示例都与这个 github 问题类似:https://github.com/DefinitelyTyped/DefinitelyTyped/issues/26146#issuecomment-393386416
我遇到的问题是我们确实改变了传递给每个中间件的 req
和 res
对象,因此我必须相应地键入两个对象:
import
Express as ExpressInterface,
Request as ExpressRequest,
Response as ExpressResponse,
NextFunction as ExpressNextFunction,
from 'express';
import LoggerType from 'some-log-package';
// don't do anything different the `next()`
export type ExpressNextFunction = ExpressNextFunction;
export interface CustomServerApp extends ExpressInterface
customHeader: string;
customLogger: LoggerType;
export interface CustomServerRequest extends ExpressRequest
app: CustomServerApp,
id: string,
urlSearchParams: URLSearchParams,
// etc
export interface CustomServerResponse extends ExpressResponse ...
所以我导出中间件的基本参数:
req
= CustomServerRequest
res
= CustomServerResponse
next
= ExpressNextFunction
当然,我会相应地将它们导入到我的中间件文件中:
import
CustomServerRequest,
CustomServerResponse,
ExpressNextFunction
from './server-types'
export const customMiddleware = (req: CustomServerRequest, res: CustomServerResponse, next: ExpressNextFunction): void
// do something here with either `req` or `res` or both!
next()
;
我们有一个集中的middleware.ts
文件,我们将所有全局中间件放入其中,因此它看起来像这样:
import CustomServerApp from './server-types';
import customMiddleware from './middlewares/customMiddleware';
export const middlewares = (app: CustomServerApp): void =>
app.use(
customMiddleware,
// maybe more middlewares, etc
);
但是,然后类型检查器运行,我收到如下错误:
No overload matches this call.
The last overload gave the following error.
Argument of type '(req: Request, res: Response, next: NextFunction) => void' is not assignable to parameter of type 'PathParams'.
Type '(req: Request, res: Response, next: NextFunction) => void' is missing the following properties from type '(string | RegExp)[]': pop, push, concat, join, and 27 more.ts(2769)
我一直很难理解为什么这会被最后一个重载定义所捕获。仅基于@types/express
,即使类型声明合并,似乎也很难向中间件处理程序添加额外的重载。
即使我遵循与核心 express 类型类似的模式来定义中间件处理程序 - https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/express-serve-static-core/index.d.ts#L40-L43 - 它也不起作用。从任何一个extend
到https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/express/index.d.ts#L99 似乎都不容易,因为您不能将泛型传递给核心 RequestHandler,这与路由器定义(IRouterHandler
、IRouterMatcher
)不同。当我尝试以这种方式输入时,我会得到不同但相似的类型错误。
有没有其他人经历过类似的事情?
【问题讨论】:
你可能想看看this answer。 【参考方案1】:您不能在 req 和 res 变量中添加必填字段,因为 express 无法满足您的约束。此外,express 在通过不同的中间件后不处理更改请求/请求类型。因此,您的自定义类型可以包含与 ExpressRequest/ExpressResponse 中相同的必填字段,其余字段应该是可选的,并且应该在中间件内进行 nullcheck。
【讨论】:
感谢您的提示,罗曼。我会仔细研究一下并报告我的发现。以上是关于Typescript - 创建自定义快速中间件定义的主要内容,如果未能解决你的问题,请参考以下文章