node.js - typescript -创建自定义快速中间件定义

标签 node.js typescript express

我一直很难为我们的应用程序定义自定义中间件。我正在使用typescript@3.6.3和express@4.17.1。

我见过的所有键入中间件的示例都暗示用户没有在reqres参数中添加任何内容,但是我知道这就是中间件的意义-改变那些对象之一,知道中间件已经以某种顺序加载(即cookie解析器或body解析器在早期是臭名昭著的,我想还是吗?)。无论如何,大多数示例都可以解决类似github问题的问题:https://github.com/DefinitelyTyped/DefinitelyTyped/issues/26146#issuecomment-393386416

我遇到的问题是,我们确实对传递给每个中间件的reqres对象进行了突变,所以我不得不相应地键入两个对象:

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,即使类型声明合并,似乎也很难向中间件处理程序添加额外的重载。

    即使当我遵循与核心表达类型相似的模式来定义中间件处理程序-https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/express-serve-static-core/index.d.ts#L40-L43时,它也不起作用。从https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/express/index.d.ts#L99extend似乎也不容易,因为与路由器定义(IRouterHandlerIRouterMatcher)不同,您无法将泛型传递给核心RequestHandler。当我尝试以这种方式键入它时,会出现不同但相似的类型错误。

    有没有其他人经历过类似的事情?

    最佳答案

    您无法在req和res变量中添加必填字段,因为express无法满足您的约束。另外,在通过不同的中间件后,express不处理更改的req/res类型。因此,您的自定义类型可以包含与ExpressRequest/ExpressResponse中相同的必填字段,其余字段应该是可选的,并且在中间件内部应具有nullcheck。

    关于node.js - typescript -创建自定义快速中间件定义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58278755/

    相关文章:

    node.js - Express js路由正在下载文件而不是渲染它

    node.js - 我们如何使用node.js获取JSON格式的响应数据

    node.js - 在 Elastic Beanstalk 上通过 .ebextensions 安装 git

    javascript - nodejs变量仅在函数和子函数中

    javascript - 遇到恼人的问题 : momentjs taking a day off by 1 with mat-datepicker for different timezones?

    node.js - 路由在 src/index.html 中不起作用

    css - 覆盖组件 HTML/在第三方组件上添加或删除 css

    node.js - JSON 作为 Sequelize 中的属性不适用于 Postgres

    node.js - Nodewebkit 应用程序的桌面通知

    javascript - 未处理的PromiseRejection警告: | DeprecationWarning: | Mongoose 5