如何给动态Router添加路由中间件?

How to add router middleware to dynamic Router?

我正在尝试将路由器中间件添加到我的 dynamically-generated 路由中。我想将一组路由器中间件传递到我的路由器,以便它可以将它们附加到我的路由。

一个路由and/or一组路由可以附加路由器中间件。这是我的类型(RouterContext 和 RouterMiddleware 来自 Oak 中间件框架):

export type RouteGroup = {
  group: { 
    prefix: string;
    middleware: Array<RouterMiddleware>;
  };
  routes: Array<Route>;
}

type Route = {
  method:
    | "all"
    | "delete"
    | "get"
    | "head"
    | "options"
    | "patch"
    | "post"
    | "put";
  path: string;
  middleware: Array<RouterMiddleware>;
  handler: (ctx: RouterContext) => Promise<void>;
}

我有一个端点(健康检查),它只是 returns 一个 200。我想用路由器中间件向它添加一个 header。这是我的路由器 class:

export class Router {
  router: OakRouter;   // imported Oak's Router class as oakRouter
  routeGroups = [
    healthcheck,
  ]
  
  constructor() {
    this.router = new OakRouter({ prefix: "/api" })
  }

  registerRoutes() {
    this._generateRoutes(this.routeGroups)
  }

  private _generateRoutes(routeGroups: RouteGroup[]) {
    routeGroups.forEach(({ group, routes }) => {
      routes.forEach(({ method, path, middleware = [], handler }) => {
        (this.router[method] as OakRouter["all"])(
          group.prefix + path, 
          [...group.middleware ?? [], ...middleware], // <-- error line
          handler
        );
      })
    })
  }
}

如果没有传递路由器中间件,我正在尝试用空数组初始化我的组中间件和路由中间件,否则传播传递的路由器中间件。无论如何,这是错误消息:

error: TS2769 [ERROR]: No overload matches this call.
  Overload 1 of 2, '(name: string, path: string, middleware: RouterMiddleware<RouteParams, Record<string, any>>, ...middlewares: RouterMiddleware<RouteParams, Record<string, any>>[]): Router<...>', gave the following error.
    Argument of type 'RouterMiddleware<RouteParams, Record<string, any>>[]' is not assignable to parameter of type 'string'.  

  Overload 2 of 2, '(path: string, middleware: RouterMiddleware<RouteParams, Record<string, any>>, ...middlewares: RouterMiddleware<RouteParams, Record<string, any>>[]): Router<...>', gave the following error.
    Argument of type 'RouterMiddleware<RouteParams, Record<string, any>>[]' is not assignable to parameter of type 'RouterMiddleware<RouteParams, Record<string, any>>'.
      Type 'RouterMiddleware<RouteParams, Record<string, any>>[]' provides no match for the signature '(context: RouterContext<RouteParams, Record<string, any>>, next: () => Promise<unknown>): unknown'.
          [...group.middleware ?? [], ...middleware], 

错误可能告诉了我我需要知道的一切,我只是不知道如何将其转化为可行的解决方案。如何更改我的中间件数组以匹配编译器正在寻找的签名?

错误说:

Argument of type 'RouterMiddleware<RouteParams, Record<string, any>>[]' is not assignable to parameter of type 'RouterMiddleware<RouteParams, Record<string, any>>'

router 方法可以将单个中间件作为第二个参数,然后是任意数量的中间件 (see the API docs)。您仍然可以对这些使用扩展语法,只是没有 []:

// Remove the first element in the array and return it
const firstMiddleware = middleware.shift();

(this.router[method] as OakRouter["all"])(
  group.prefix + path,
  firstMiddleware,
  ...group.middleware,
  ...middleware,
  handler,
);