It's so good to have Typescript support for route path an path params, just like Tanstack Router 🔥
With this, everyone will have a better DX.
Suggested solution
Instead of using a static declaration file, we should generate one.
Wrapping react-router-dom/vue-router API to using types from generated declaration file. Then exports them.
Example:
// Generated declaration file
declare module '~react-pages' {
import type { RouteObject } from 'react-router'
import type { NavigateOptions, LinkProps } from 'react-router-dom'
// Generated route paths
export type RoutePaths = "/posts" | "/posts/:id";
// Declare function generatePath
type Split<T extends string> = T extends `${infer P}/`
? Split<P>
: T extends `/${infer P}`
? Split<P>
: T extends `${infer PL}/${infer PR}`
? Split<PL> | Split<PR>
: T;
type PathParamsKey<T extends string, K = Split<T>> = K extends `:${infer P}`
? P
: K extends `...${infer P}`
? P
: // eslint-disable-next-line @typescript-eslint/no-unused-vars
K extends `${infer _P}*`
? "slug"
: never;
type PathParams<T extends string> = {
[P in PathParamsKey<T>]: string | number;
};
export type GeneratePathOptions<
T extends string,
Params extends object = PathParams<T>
> = {
path: T;
} & (keyof Params extends never ? { params?: Params } : { params: Params });
export function generatePath<T extends string = RoutePaths>({
path,
params,
}: GeneratePathOptions<T>): string;
// Declare hook useNavigate
export function useNavigate(): <T extends string = RoutePaths>(
pathOptions: GeneratePathOptions<T>,
options?: NavigateOptions
) => void
// Declare component Link
export function Link<T extends string = RoutePaths>(
props: GeneratePathOptions<T> &
Omit<LinkProps, "to">
): void
// Export routes
const routes: RouteObject[]
export default routes
}
declare module 'virtual:generated-pages-react' {
import type { RouteObject } from 'react-router'
const routes: RouteObject[]
export default routes
}
// Function generatePath
export default function generatePath<T extends string>({
path,
params,
}: GeneratePathOptions<T>): string {
let result: string = path;
if (params) {
for (const key in params) {
if (Object.prototype.hasOwnProperty.call(params, key)) {
const value = params[key as keyof typeof params] as string;
result = result.replace(`:${key}`, value);
}
}
if ("slug" in params && result.endsWith("*")) {
result = result.replace(/\*$/, params.slug as string);
}
}
return result;
}
Then, we should exports generatePath, useNavigate and Link in virtual module, which currently only exports routes.
Description
It's so good to have Typescript support for route path an path params, just like Tanstack Router 🔥
With this, everyone will have a better DX.
Suggested solution
react-router-dom
/vue-router
API to using types from generated declaration file. Then exports them.Example:
Then, we should exports
generatePath
,useNavigate
andLink
in virtual module, which currently only exportsroutes
.Alternative
No response
Additional context
No response
Validations