+> {
+ // tslint:disable-next-line callable-types (This is extended from and can't extend from a type alias in ts<2.2)
+ (
+ req: Request,
+ res: Response,
+ next: NextFunction,
+ ): void;
+}
+
+export type ErrorRequestHandler<
+ P = ParamsDictionary,
+ ResBody = any,
+ ReqBody = any,
+ ReqQuery = ParsedQs,
+ Locals extends Record = Record
+> = (
+ err: any,
+ req: Request,
+ res: Response,
+ next: NextFunction,
+) => void;
+
+export type PathParams = string | RegExp | Array;
+
+export type RequestHandlerParams<
+ P = ParamsDictionary,
+ ResBody = any,
+ ReqBody = any,
+ ReqQuery = ParsedQs,
+ Locals extends Record = Record
+> =
+ | RequestHandler
+ | ErrorRequestHandler
+ | Array | ErrorRequestHandler>;
+
+type RemoveTail = S extends `${infer P}${Tail}` ? P : S;
+type GetRouteParameter = RemoveTail<
+ RemoveTail, `-${string}`>,
+ `.${string}`
+>;
+
+// prettier-ignore
+export type RouteParameters = string extends Route
+ ? ParamsDictionary
+ : Route extends `${string}(${string}`
+ ? ParamsDictionary //TODO: handling for regex parameters
+ : Route extends `${string}:${infer Rest}`
+ ? (
+ GetRouteParameter extends never
+ ? ParamsDictionary
+ : GetRouteParameter extends `${infer ParamName}?`
+ ? { [P in ParamName]?: string }
+ : { [P in GetRouteParameter]: string }
+ ) &
+ (Rest extends `${GetRouteParameter}${infer Next}`
+ ? RouteParameters : unknown)
+ : {};
+
+export interface IRouterMatcher<
+ T,
+ Method extends 'all' | 'get' | 'post' | 'put' | 'delete' | 'patch' | 'options' | 'head' = any
+> {
+ <
+ Route extends string,
+ P = RouteParameters,
+ ResBody = any,
+ ReqBody = any,
+ ReqQuery = ParsedQs,
+ Locals extends Record = Record
+ >(
+ // tslint:disable-next-line no-unnecessary-generics (it's used as the default type parameter for P)
+ path: Route,
+ // tslint:disable-next-line no-unnecessary-generics (This generic is meant to be passed explicitly.)
+ ...handlers: Array>
+ ): T;
+ <
+ Path extends string,
+ P = RouteParameters,
+ ResBody = any,
+ ReqBody = any,
+ ReqQuery = ParsedQs,
+ Locals extends Record = Record
+ >(
+ // tslint:disable-next-line no-unnecessary-generics (it's used as the default type parameter for P)
+ path: Path,
+ // tslint:disable-next-line no-unnecessary-generics (This generic is meant to be passed explicitly.)
+ ...handlers: Array>
+ ): T;
+ <
+ P = ParamsDictionary,
+ ResBody = any,
+ ReqBody = any,
+ ReqQuery = ParsedQs,
+ Locals extends Record = Record
+ >(
+ path: PathParams,
+ // tslint:disable-next-line no-unnecessary-generics (This generic is meant to be passed explicitly.)
+ ...handlers: Array>
+ ): T;
+ <
+ P = ParamsDictionary,
+ ResBody = any,
+ ReqBody = any,
+ ReqQuery = ParsedQs,
+ Locals extends Record = Record
+ >(
+ path: PathParams,
+ // tslint:disable-next-line no-unnecessary-generics (This generic is meant to be passed explicitly.)
+ ...handlers: Array>
+ ): T;
+ (path: PathParams, subApplication: Application): T;
+}
+
+export interface IRouterHandler {
+ (...handlers: Array>>): T;
+ (...handlers: Array>>): T;
+ <
+ P = RouteParameters,
+ ResBody = any,
+ ReqBody = any,
+ ReqQuery = ParsedQs,
+ Locals extends Record = Record
+ >(
+ // tslint:disable-next-line no-unnecessary-generics (This generic is meant to be passed explicitly.)
+ ...handlers: Array>
+ ): T;
+ <
+ P = RouteParameters,
+ ResBody = any,
+ ReqBody = any,
+ ReqQuery = ParsedQs,
+ Locals extends Record = Record
+ >(
+ // tslint:disable-next-line no-unnecessary-generics (This generic is meant to be passed explicitly.)
+ ...handlers: Array>
+ ): T;
+ <
+ P = ParamsDictionary,
+ ResBody = any,
+ ReqBody = any,
+ ReqQuery = ParsedQs,
+ Locals extends Record = Record
+ >(
+ // tslint:disable-next-line no-unnecessary-generics (This generic is meant to be passed explicitly.)
+ ...handlers: Array>
+ ): T;
+ <
+ P = ParamsDictionary,
+ ResBody = any,
+ ReqBody = any,
+ ReqQuery = ParsedQs,
+ Locals extends Record = Record
+ >(
+ // tslint:disable-next-line no-unnecessary-generics (This generic is meant to be passed explicitly.)
+ ...handlers: Array>
+ ): T;
+}
+
+export interface IRouter extends RequestHandler {
+ /**
+ * Map the given param placeholder `name`(s) to the given callback(s).
+ *
+ * Parameter mapping is used to provide pre-conditions to routes
+ * which use normalized placeholders. For example a _:user_id_ parameter
+ * could automatically load a user's information from the database without
+ * any additional code,
+ *
+ * The callback uses the samesignature as middleware, the only differencing
+ * being that the value of the placeholder is passed, in this case the _id_
+ * of the user. Once the `next()` function is invoked, just like middleware
+ * it will continue on to execute the route, or subsequent parameter functions.
+ *
+ * app.param('user_id', function(req, res, next, id){
+ * User.find(id, function(err, user){
+ * if (err) {
+ * next(err);
+ * } else if (user) {
+ * req.user = user;
+ * next();
+ * } else {
+ * next(new Error('failed to load user'));
+ * }
+ * });
+ * });
+ */
+ param(name: string, handler: RequestParamHandler): this;
+
+ /**
+ * Alternatively, you can pass only a callback, in which case you have the opportunity to alter the app.param()
+ *
+ * @deprecated since version 4.11
+ */
+ param(callback: (name: string, matcher: RegExp) => RequestParamHandler): this;
+
+ /**
+ * Special-cased "all" method, applying the given route `path`,
+ * middleware, and callback to _every_ HTTP method.
+ */
+ all: IRouterMatcher;
+ get: IRouterMatcher;
+ post: IRouterMatcher;
+ put: IRouterMatcher;
+ delete: IRouterMatcher;
+ patch: IRouterMatcher;
+ options: IRouterMatcher;
+ head: IRouterMatcher;
+
+ checkout: IRouterMatcher;
+ connect: IRouterMatcher;
+ copy: IRouterMatcher;
+ lock: IRouterMatcher;
+ merge: IRouterMatcher;
+ mkactivity: IRouterMatcher;
+ mkcol: IRouterMatcher;
+ move: IRouterMatcher;
+ 'm-search': IRouterMatcher;
+ notify: IRouterMatcher;
+ propfind: IRouterMatcher;
+ proppatch: IRouterMatcher;
+ purge: IRouterMatcher;
+ report: IRouterMatcher;
+ search: IRouterMatcher;
+ subscribe: IRouterMatcher;
+ trace: IRouterMatcher;
+ unlock: IRouterMatcher;
+ unsubscribe: IRouterMatcher;
+
+ use: IRouterHandler & IRouterMatcher;
+
+ route(prefix: T): IRoute;
+ route(prefix: PathParams): IRoute;
+ /**
+ * Stack of configured routes
+ */
+ stack: any[];
+}
+
+export interface IRoute {
+ path: string;
+ stack: any;
+ all: IRouterHandler;
+ get: IRouterHandler;
+ post: IRouterHandler;
+ put: IRouterHandler;
+ delete: IRouterHandler;
+ patch: IRouterHandler;
+ options: IRouterHandler;
+ head: IRouterHandler;
+
+ checkout: IRouterHandler;
+ copy: IRouterHandler;
+ lock: IRouterHandler;
+ merge: IRouterHandler;
+ mkactivity: IRouterHandler;
+ mkcol: IRouterHandler;
+ move: IRouterHandler;
+ 'm-search': IRouterHandler;
+ notify: IRouterHandler;
+ purge: IRouterHandler