[Feature] Typescript support for route path and route path params(Auto complete)
niku98 opened this issue · comments
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
- 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
.
Alternative
No response
Additional context
No response
Validations
- Follow the Code of Conduct
- Read the docs.
- Check that there isn't already an issue that request the same feature to avoid creating a duplicate.
Out of scope and not planning to do.
Maybe someone can make a react version of unplugin-vue-router.