Type routes with the satisfies operator
TypeScript
// `satisfies` checks the shape while keeping literal route names intact.
type Route = { path: string; auth: boolean; title: string };
const routes = {
home: { path: '/', auth: false, title: 'Home' },
settings: { path: '/settings', auth: true, title: 'Settings' },
admin: { path: '/admin', auth: true, title: 'Admin' },
} satisfies Record<string, Route>;
type RouteName = keyof typeof routes; // 'home' | 'settings' | 'admin'
function buildUrl(name: RouteName, params: Record<string, string> = {}): string {
const route: Route = routes[name];
const url = new URL(route.path, 'https://example.com');
for (const [key, value] of Object.entries(params)) {
url.searchParams.set(key, value);
}
return url.pathname + url.search;
}
console.log(buildUrl('settings', { tab: 'profile' })); // /settings?tab=profile
console.log(buildUrl('home')); // /
// buildUrl('missing'); // type error: "missing" is not a RouteName