T8 React Router
Type safety
Type-safe routing is as an optional enhancement. It's enabled by supporting route patterns created with a type-safe URL builder like url-shape together with a schema created with zod or yup. This approach allows for gradual or partial adoption of type-safe routing in an application.
import { A, useRoute } from "@t8/react-router";
import { createURLSchema } from "url-shape";
import { z } from "zod";
const { url } = createURLSchema({
"/": null, // Goes without parameters
"/sections/:id": {
// Path components
params: z.object({
id: z.coerce.number(),
}),
// Similarly a `query` schema can be added here
},
});
let App = () => {
let { withRoute } = useRoute();
return (
<>
<header className={withRoute(url("/"), "full", "compact")}>
<h1>App</h1>
<nav>
<A href={url("/")}>Intro</A>{" | "}
<A href={url("/sections/:id", { params: { id: 1 } })}>Start</A>
</nav>
</header>
{withRoute(url("/"), <Intro/>)}
{withRoute(url("/sections/:id"), ({ params }) => (
<Section id={params.id}/>
))}
</>
);
};
🔹 The url()
function is a type-safe URL builder. It creates a URL with a URL pattern defined in the schema and typed parameters that are prevalidated against the given schema: typos and type mismatches are highlighted in a type-aware code editor. See url-shape for more details.
🔹 A URL schema doesn't have to cover the entire app. Standalone portions of an app can have their own URL schemas.
🔹 Optionally, application-wide type safety can be achieved by disallowing URLs and URL patterns other than provided by the URL builder (the url()
function in the example above):
declare module "@t8/react-router" {
interface Config {
strict: true;
}
}
Adding this type declaration to an app effectively disallows using string
and RegExp
values for routes and route patterns (such as in the route link href
prop, route.assign(location)
, and the routing function withRoute(routePattern, x, y)
), only allowing values returned from the URL builder with the same routing APIs.
🔹 A URL builder pattern (like url("/sections/:id")
) can also be used with useRouteState(pattern)
and useRouteMatch(pattern)
to manipulate URL parameters in a type-safe manner.
Typed URL parameters state demo
🔹 Recap: It's using a typed URL pattern (like with url()
from url-shape) that enables type-safe route handling, which is an optional enhancement. Plain string
routes and RegExp
route patterns are handled with more generic typing as a baseline sufficient in many cases.