Type-Safe Routing
Kimesh generates TypeScript definitions for your routes, providing full type safety for navigation and params.
Generated Types
When you run the development server, Kimesh generates type definitions in .kimesh/typed-routes.d.ts:
// Auto-generated route types
export interface RouteNamedMap {
index: RouteRecordInfo<'index', '/', {}, {}>
about: RouteRecordInfo<'about', '/about', {}, {}>
posts: RouteRecordInfo<'posts', '/posts', {}, {}>
'posts-postId': RouteRecordInfo<'posts-postId', '/posts/:postId', { postId: string | number }, { postId: string }>
}Type-Safe Navigation
Using KmLink
The KmLink component provides type-safe navigation:
<script setup lang="ts">
import { KmLink } from '@kimesh/router-runtime'
</script>
<template>
<!-- Type-safe route with params -->
<KmLink to="/posts/:postId" :params="{ postId: post.id }">
{{ post.title }}
</KmLink>
<!-- Simple route without params -->
<KmLink to="/about">About</KmLink>
</template>Using useNavigate
Navigate programmatically with type checking:
import { useNavigate } from '@kimesh/router-runtime'
const navigate = useNavigate()
function goToPost(id: string) {
navigate('/posts/:postId', { params: { postId: id } })
}
function goHome() {
navigate('/')
}Using useRouter
Standard Vue Router navigation:
import { useRouter } from '@kimesh/router-runtime'
const router = useRouter()
function navigateToPost(id: string) {
router.push({ name: 'posts-postId', params: { postId: id } })
}Route Params
useParams
Access current route params:
import { useParams } from '@kimesh/router-runtime'
// Non-reactive, use for initial values
const params = useParams<'/posts/:postId'>()
console.log(params.postId) // stringuseReactiveParams
Reactive params that update on navigation:
import { useReactiveParams } from '@kimesh/router-runtime'
// Reactive - updates when route changes
const params = useReactiveParams<'/posts/:postId'>()
// Use .value to access
console.log(params.value.postId)Param Types
Different param patterns generate different types:
| File Pattern | URL Pattern | Type |
|---|---|---|
$id.vue | :id | string |
$id/ (directory) | :id | string |
$.vue | :pathMatch(.*)* | string[] |
Search Params
useSearch
Access and manipulate typed search/query params:
import { useSearch } from '@kimesh/router-runtime'
import { z } from 'zod'
const searchSchema = z.object({
page: z.coerce.number().default(1),
sort: z.enum(['asc', 'desc']).default('desc'),
})
const { search, setSearch, setAllSearch, resetSearch } = useSearch(searchSchema)
// Read validated values
console.log(search.value.page) // number (not string!)
// Update single param (updates URL)
setSearch('page', 2)
// Update multiple params
setAllSearch({ page: 1, sort: 'asc' })
// Reset to defaults
resetSearch()Validation with Zod
Use validateSearch in createFileRoute for validated search params:
import { createFileRoute } from '@kimesh/router-runtime'
import { z } from 'zod'
const searchSchema = z.object({
page: z.coerce.number().default(1),
sort: z.enum(['newest', 'oldest']).default('newest'),
tag: z.string().optional(),
})
export const Route = createFileRoute('/posts')({
validateSearch: searchSchema,
loader: async ({ search, context }) => {
// search is typed as { page: number, sort: 'newest' | 'oldest', tag?: string }
console.log(search.page) // number, not string
},
})Type Utilities
RouteNames
Get all valid route names:
import type { RouteNames } from '@kimesh/router-runtime'
// RouteNames = 'index' | 'about' | 'posts' | 'posts-postId' | ...
function logRoute(name: RouteNames) {
console.log(`Navigating to ${name}`)
}RouteParams<T>
Get params type for a specific route:
import type { RouteParams } from '@kimesh/router-runtime'
type PostParams = RouteParams<'posts-postId'>
// PostParams = { postId: string }RoutePath<T>
Get the path template for a route:
import type { RoutePath } from '@kimesh/router-runtime'
type PostPath = RoutePath<'posts-postId'>
// PostPath = '/posts/:postId'HasParams<T>
Check if a route has params:
import type { HasParams } from '@kimesh/router-runtime'
type IndexHasParams = HasParams<'index'> // false
type PostHasParams = HasParams<'posts-postId'> // trueLoader Type Safety
Type your loaders with generic params:
// In your route file's <script lang="ts"> block
import { createFileRoute } from '@kimesh/router-runtime'
import { postDetailQuery } from './posts.data'
export const Route = createFileRoute('/posts/:postId')({
loader: async ({ params, context }) => {
// params.postId is typed as string
await context.queryClient.ensureQueryData(postDetailQuery(params.postId))
},
})IDE Support
VS Code
Install the Vue - Official extension for:
- Route path autocomplete in
KmLink - Param type checking
- Jump to route file definition
TypeScript Configuration
Ensure your tsconfig.json includes the generated types:
{
"compilerOptions": {
"strict": true,
"moduleResolution": "bundler"
},
"include": ["src/**/*.ts", "src/**/*.vue", ".kimesh/**/*.ts"]
}