Type-safe routing
As an optional enhancement, Routescape supports progressive schema-based route type safety.
Type-safe routing is enabled by Routescape's support of routes created with a type-safe URL builder like url-shape
coupled 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 'routescape';
import {createURLSchema} from 'url-shape';
import {z} from 'zod';
const {url} = createURLSchema({
'/': null, // goes without parameters
'/sections/:id': {
params: z.object({
id: z.coerce.number(),
}),
},
'/search': {
query: z.object({
term: z.string(),
lang: z.optional(z.enum(['current', 'all'])),
}),
},
});
let App = () => {
let {withRoute} = useRoute();
// `withRoute(routePattern, x, y)` acts similarly to
// `matchesRoutePattern ? x : y`
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('/'), (
<main>
<h1>Intro</h1>
</main>
))}
{withRoute(url('/sections/:id'), ({params}) => (
<main>
<h1>Section {params.id}</h1>
</main>
))}
</>
);
};
🔹 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.
🔹 For more details on the output of the createURLSchema()
, such as url()
, match()
, validate()
, and the null
-schema mode, see the description of url-shape
.
🔹 A URL schema doesn't have to cover the entire app. Standalone portions of an app can have their own URL schemas.
🔹 Stricter 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) throughout the app:
declare module 'routescape' {
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 ternary route-matching 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 useRouteMatch(pattern)
and useRouteState(pattern)
to manipulate URL parameters in a type-safe manner.
Typed URL parameters state demo
← URL parameters | GitHub ✦