@@ -42,10 +42,13 @@ export interface Dictionary<T> {
4242}
4343
4444export interface ParamsDictionary {
45- [ key : string ] : string ;
45+ [ key : string ] : string | string [ ] ;
46+ [ key : number ] : string ;
4647}
47- export type ParamsArray = string [ ] ;
48- export type Params = ParamsDictionary | ParamsArray ;
48+ export interface ParamsFlatDictionary {
49+ [ key : string | number ] : string ;
50+ }
51+ export type Params = ParamsDictionary | ParamsFlatDictionary ;
4952
5053export interface Locals extends Express . Locals { }
5154
@@ -96,20 +99,26 @@ type GetRouteParameter<S extends string> = RemoveTail<
9699 `.${string } `
97100> ;
98101
99- // prettier-ignore
100- export type RouteParameters < Route extends string > = Route extends `${infer Required } {${infer Optional } }${infer Next } `
101- ? ParseRouteParameters < Required > & Partial < ParseRouteParameters < Optional > > & RouteParameters < Next >
102- : ParseRouteParameters < Route > ;
102+ // dprint-ignore
103+ export type RouteParameters < Route extends string | RegExp > = Route extends string
104+ ? Route extends `${infer Required } {${infer Optional } }${infer Next } `
105+ ? ParseRouteParameters < Required > & Partial < ParseRouteParameters < Optional > > & RouteParameters < Next >
106+ : ParseRouteParameters < Route >
107+ : ParamsFlatDictionary ;
103108
104109type ParseRouteParameters < Route extends string > = string extends Route ? ParamsDictionary
105- : Route extends `${string } (${string } ` ? ParamsDictionary // TODO: handling for regex parameters
106110 : Route extends `${string } :${infer Rest } ` ?
107111 & (
108112 GetRouteParameter < Rest > extends never ? ParamsDictionary
109- : GetRouteParameter < Rest > extends `${infer ParamName } ?` ? { [ P in ParamName ] ?: string } // TODO: Remove old `?` handling when Express 5 is promoted to "latest"
110113 : { [ P in GetRouteParameter < Rest > ] : string }
111114 )
112115 & ( Rest extends `${GetRouteParameter < Rest > } ${infer Next } ` ? RouteParameters < Next > : unknown )
116+ : Route extends `${string } *${infer Rest } ` ?
117+ & (
118+ GetRouteParameter < Rest > extends never ? ParamsDictionary
119+ : { [ P in GetRouteParameter < Rest > ] : string [ ] }
120+ )
121+ & ( Rest extends `${GetRouteParameter < Rest > } ${infer Next } ` ? RouteParameters < Next > : unknown )
113122 : { } ;
114123
115124/* eslint-disable @definitelytyped/no-unnecessary-generics */
@@ -118,7 +127,7 @@ export interface IRouterMatcher<
118127 Method extends "all" | "get" | "post" | "put" | "delete" | "patch" | "options" | "head" = any ,
119128> {
120129 <
121- Route extends string ,
130+ Route extends string | RegExp ,
122131 P = RouteParameters < Route > ,
123132 ResBody = any ,
124133 ReqBody = any ,
@@ -131,7 +140,7 @@ export interface IRouterMatcher<
131140 ...handlers : Array < RequestHandler < P , ResBody , ReqBody , ReqQuery , LocalsObj > >
132141 ) : T ;
133142 <
134- Path extends string ,
143+ Path extends string | RegExp ,
135144 P = RouteParameters < Path > ,
136145 ResBody = any ,
137146 ReqBody = any ,
@@ -168,7 +177,7 @@ export interface IRouterMatcher<
168177 ( path : PathParams , subApplication : Application ) : T ;
169178}
170179
171- export interface IRouterHandler < T , Route extends string = string > {
180+ export interface IRouterHandler < T , Route extends string | RegExp = string > {
172181 ( ...handlers : Array < RequestHandler < RouteParameters < Route > > > ) : T ;
173182 ( ...handlers : Array < RequestHandlerParams < RouteParameters < Route > > > ) : T ;
174183 <
@@ -284,7 +293,7 @@ export interface IRouter extends RequestHandler {
284293
285294 use : IRouterHandler < this> & IRouterMatcher < this> ;
286295
287- route < T extends string > ( prefix : T ) : IRoute < T > ;
296+ route < T extends string | RegExp > ( prefix : T ) : IRoute < T > ;
288297 route ( prefix : PathParams ) : IRoute ;
289298 /**
290299 * Stack of configured routes
@@ -303,7 +312,7 @@ export interface ILayer {
303312 handle : ( req : Request , res : Response , next : NextFunction ) => any ;
304313}
305314
306- export interface IRoute < Route extends string = string > {
315+ export interface IRoute < Route extends string | RegExp = string > {
307316 path : string ;
308317 stack : ILayer [ ] ;
309318 all : IRouterHandler < this, Route > ;
@@ -381,16 +390,14 @@ export type Errback = (err: Error) => void;
381390
382391/**
383392 * @param P For most requests, this should be `ParamsDictionary`, but if you're
384- * using this in a route handler for a route that uses a `RegExp` or a wildcard
385- * `string` path (e.g. `'/user/*'`), then `req.params` will be an array, in
386- * which case you should use `ParamsArray` instead.
387- *
388- * @see https://expressjs.com/en/api.html#req.params
393+ * using this in a route handler for a route that uses a `RegExp`, then `req.params`
394+ * will only contains strings, in which case you should use `ParamsFlatDictionary` instead.
389395 *
390396 * @example
391- * app.get('/user/:id', (req, res) => res.send(req.params.id)); // implicitly `ParamsDictionary`
392- * app.get<ParamsArray>(/user\/(.*)/, (req, res) => res.send(req.params[0]));
393- * app.get<ParamsArray>('/user/*', (req, res) => res.send(req.params[0]));
397+ * app.get('/user/:id', (req, res) => res.send(req.params.id)); // implicitly `ParamsDictionary`, parameter is string
398+ * app.get('/user/*id', (req, res) => res.send(req.params.id)); // implicitly `ParamsDictionary`, parameter is string[]
399+ * app.get(/user\/(?<id>.*)/, (req, res) => res.send(req.params.id)); // implicitly `ParamsFlatDictionary`, parameter is string
400+ * app.get(/user\/(.*)/, (req, res) => res.send(req.params[0])); // implicitly `ParamsFlatDictionary`, parameter is string
394401 */
395402export interface Request <
396403 P = ParamsDictionary ,
0 commit comments