From 417010a9fd6a3f9f893c9dd74dfdb4ce70823097 Mon Sep 17 00:00:00 2001 From: John <12599934+jorroll@users.noreply.github.com> Date: Tue, 21 Dec 2021 19:52:04 -0800 Subject: [PATCH 1/2] fix: PathParams type --- lib/middleware/router.ts | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/lib/middleware/router.ts b/lib/middleware/router.ts index a5ac18e..a51d7cd 100644 --- a/lib/middleware/router.ts +++ b/lib/middleware/router.ts @@ -40,20 +40,25 @@ export type RouteHandlerMatch = { matches?: RegExpExecArray; } & Route>>; -export type SplitRoute = string extends S ? string[] - : S extends `${infer Start}/:${infer Param}/${infer Rest}` - ? [Param, ...SplitRoute] - : S extends `${infer Start}/:${infer Param}+` ? [Param] - : S extends `${infer Start}/:${infer Param}` ? [Param] - : []; - -export type PathParams = - & { - [P in SplitRoute[number]]: string; - } - & { - [P in SplitRoute[number]]?: string; - }; +/** Split type `"one/two/three"` into `["one", "two", "three"]` */ +type SplitPath = + string extends S ? string[] : + S extends `${infer A}/${infer B}` ? [A, ...SplitPath] : + [S]; + +/** Convert type `"one" | ":two" | ":three"` into `"two" | "three"` */ +type ExtractParams = + string extends S ? string : + S extends `:${infer A}` ? A : + never; + +/** + * Convert a route path string literal type such as "one/:two/:three" + * into a params interface like `{ two: string; three: string }` + */ +export type PathParams = { + [P in ExtractParams[number]>]: string; +}; /** * Router wraps the tiny-request-router `Router` with a more strict RouteHandler type and automatic params typings. From effc2a99da29ffccac67294e5cf8eac985344a2c Mon Sep 17 00:00:00 2001 From: John <12599934+jorroll@users.noreply.github.com> Date: Tue, 11 Jan 2022 17:40:56 -0800 Subject: [PATCH 2/2] feat: support optional params in PathParams type --- lib/middleware/router.ts | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/lib/middleware/router.ts b/lib/middleware/router.ts index a51d7cd..31abbef 100644 --- a/lib/middleware/router.ts +++ b/lib/middleware/router.ts @@ -40,24 +40,33 @@ export type RouteHandlerMatch = { matches?: RegExpExecArray; } & Route>>; -/** Split type `"one/two/three"` into `["one", "two", "three"]` */ +/** Split type `"one/:two/:three?/:four"` into `["one", ":two", ":three?", ":four"]` */ type SplitPath = string extends S ? string[] : S extends `${infer A}/${infer B}` ? [A, ...SplitPath] : [S]; -/** Convert type `"one" | ":two" | ":three"` into `"two" | "three"` */ -type ExtractParams = +/** Convert type `"one" | ":two" | ":three?" | ":four"` into `"two" | "four"` */ +type ExtractRequiredParams = string extends S ? string : + S extends `:${infer A}?` ? never : S extends `:${infer A}` ? A : never; +/** Convert type `"one" | ":two" | ":three?" | ":four"` into `"three"` */ +type ExtractOptionalParams = + string extends S ? string : + S extends `:${infer A}?` ? A : + never; + /** - * Convert a route path string literal type such as "one/:two/:three" - * into a params interface like `{ two: string; three: string }` + * Convert a route path string literal type such as "one/:two/:three?/:four" + * into a params interface like `{ two: string; three?: string; four: string }` */ -export type PathParams = { - [P in ExtractParams[number]>]: string; + export type PathParams = { + [P in ExtractRequiredParams[number]>]: string; +} & { + [P in ExtractOptionalParams[number]>]?: string; }; /**