I saw the rejected URL2Json type, but hear me out:
Many routing libraries parse params from a path defined like /users/{id?}, which is often a constant in code.
Think of this example: https://reactrouter.com/en/main/route/route
const router = createBrowserRouter([
{
// it renders this element
element: <Team />,
// when the URL matches this segment
path: "teams/:teamId",
// with this data loaded before rendering
loader: async ({ request, params }) => {
return fetch(
`/fake/api/teams/${params.teamId}.json`, // <- params is of type Record<string, string>, we can do better
{ signal: request.signal }
);
},
// performing this mutation when data is submitted to it
action: async ({ request }) => {
return updateFakeTeam(await request.formData());
},
// and renders this element in case something went wrong
errorElement: <ErrorBoundary />,
},
]);
Somewhat working example (but also breaking):
import type { Merge } from "type-fest";
type PathParams<S> = ExtractPathParams<S> extends EmptyObject
? Record<string, string>
: ExtractPathParams<S>;
type ExtractPathParams<S> = S extends `${infer _}{${infer Param}?}${infer Tail}`
? Param extends `${infer Head}}${infer Rest}`
? Merge<Record<Head, string>, ExtractPathParams<`${Rest}?}${Tail}`>>
: Merge<Partial<Record<Param, string>>, ExtractPathParams<Tail>>
: S extends `${infer _}{${infer Param}}${infer Tail}`
? Merge<Record<Param, string>, ExtractPathParams<Tail>>
: {};
type Params = PathParams<'teams/{teamId?}'>; // Partial<Record<'teamId', string>>
Ideally this should be the responsibility of the library itself, but having a generic one in type-fest might make some people happy.
Upvote & Fund
We're using Polar.sh so you can upvote and help fund this issue.
The funding will be given to active contributors.
Thank you in advance for helping prioritize & fund our backlog.
I saw the rejected URL2Json type, but hear me out:
Many routing libraries parse params from a path defined like
/users/{id?}
, which is often a constant in code. Think of this example: https://reactrouter.com/en/main/route/routeSomewhat working example (but also breaking):
Ideally this should be the responsibility of the library itself, but having a generic one in type-fest might make some people happy.
Upvote & Fund