Skip to content

Instantly share code, notes, and snippets.

@gabrielelana
Created August 3, 2022 15:06
Show Gist options
  • Save gabrielelana/24d5715d26c48b2859217a112992f7f6 to your computer and use it in GitHub Desktop.
Save gabrielelana/24d5715d26c48b2859217a112992f7f6 to your computer and use it in GitHub Desktop.
Typescript utility type to parse route parameters
type Tuple<X, Y> = [X, Y]
type Equal<X, Y> =
(<T>() => T extends X ? 1 : 2) extends
(<T>() => T extends Y ? 1 : 2) ? Tuple<true, Y> : Tuple<false, Y>
type Assert<T extends Tuple<true, any>> = T[1];//
// P = collecting param names
// N = current param name
// I = true if we are collecting a name
type RouteParameters<R extends string, P extends string = never, N extends string = "", I extends boolean = false> =
R extends `${infer C}${infer T}`
? C extends ":"
? RouteParameters<T, P, N, true>
: C extends "/" | "." | "-"
? I extends true
? RouteParameters<T, P|N, "", false>
: RouteParameters<T, P, N, I>
: I extends true
? RouteParameters<T, P, `${N}${C}`, I>
: RouteParameters<T, P, N, I>
: R extends `${infer C}`
? C extends ""
? I extends true
? {[K in P | `${C}${N}`]: string}
: {[K in P]: string}
: {[K in P]: string}
: {[K in P]: string}
type tests = [
Assert<Equal<{}, RouteParameters<"">>>,
Assert<Equal<{}, RouteParameters<"/foo">>>,
Assert<Equal<{}, RouteParameters<"/foo/bar">>>,
Assert<Equal<{foo: string}, RouteParameters<"/:foo">>>,
Assert<Equal<{foo: string}, RouteParameters<"/:foo/">>>,
Assert<Equal<{foo: string}, RouteParameters<"/:foo/bar">>>,
Assert<Equal<{foo: string}, RouteParameters<"/bar/:foo">>>,
Assert<Equal<{foo: string}, RouteParameters<"/bar/:foo/baz">>>,
Assert<Equal<{foo: string, bar: string}, RouteParameters<"/:foo/:bar">>>,
Assert<Equal<{foo: string, bar: string, baz: string}, RouteParameters<"/:foo/:bar/:baz">>>,
Assert<Equal<{userId: string, bookId: string}, RouteParameters<"/users/:userId/books/:bookId">>>,
Assert<Equal<{from: string, to: string}, RouteParameters<"/flights/:from-:to">>>,
Assert<Equal<{genus: string, species: string}, RouteParameters<"/plantae/:genus.:species">>>,
];
@gabrielelana
Copy link
Author

@ghost Not supported but not hard to implement

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment