Overview
Ziggy includes comprehensive TypeScript type definitions that provide:
Type-safe route generation
Route name autocompletion
Parameter validation
Return type safety
Optional strict type checking
The base package includes generic types, but you can generate route-specific types for full autocomplete and validation.
Basic TypeScript Usage
Ziggy’s types work out of the box without any additional setup:
import { route } from 'ziggy-js' ;
import type { RouteUrl , Config } from 'ziggy-js' ;
// route() returns a RouteUrl (branded string type)
const url : RouteUrl = route ( 'posts.show' , { post: 1 });
// You can pass route names as strings
const home = route ( 'home' );
// Parameters can be objects, arrays, or single values
route ( 'posts.show' , { post: 1 });
route ( 'posts.show' , [ 1 ]);
route ( 'posts.show' , 1 );
Generating Route Types
To enable route name and parameter autocompletion, generate TypeScript definitions from your Laravel routes:
php artisan ziggy:generate --types
This creates resources/js/ziggy.d.ts (or ziggy-routes.d.ts) with types for all your routes:
// resources/js/ziggy.d.ts (generated)
export interface RouteList {
'home' : [],
'posts.index' : [],
'posts.show' : [
{ name : 'post' , required : true , binding ?: 'id' },
],
'posts.update' : [
{ name : 'post' , required : true , binding ?: 'id' },
],
'venues.events.show' : [
{ name : 'venue' , required : true },
{ name : 'event' , required : true },
],
}
Generate Types with Config
Generate both the Ziggy config file and TypeScript types:
php artisan ziggy:generate --types
Generate Only Types
Generate only the TypeScript definitions without the config:
php artisan ziggy:generate --types-only
Custom Output Path
php artisan ziggy:generate --types resources/js/types/ziggy.d.ts
Global Route Function
If you’re using the @routes Blade directive, declare the global route function to make TypeScript aware of it:
// global.d.ts or ziggy-global.d.ts
import { route as routeFn } from 'ziggy-js' ;
declare global {
var route : typeof routeFn ;
}
export {};
Now you can use route() globally without imports:
// No import needed
const url = route ( 'posts.show' , { post: 1 });
tsconfig.json Setup
If you don’t have the ziggy-js NPM package installed, add a path alias to load types from your vendor directory:
{
"compilerOptions" : {
"paths" : {
"ziggy-js" : [ "./vendor/tightenco/ziggy" ]
}
}
}
This allows TypeScript to find Ziggy’s types even when you’re importing from the vendor folder:
import { route } from 'ziggy-js' ;
Strict Route Name Checking
By default, TypeScript allows passing any string to route(), even if type definitions are generated. Enable strict checking to only allow known route names:
// ziggy-strict.d.ts
declare module 'ziggy-js' {
interface TypeConfig {
strictRouteNames : true ;
}
}
export {};
With strict checking enabled:
import { route } from 'ziggy-js' ;
// ✓ Valid - route exists
route ( 'posts.show' , { post: 1 });
// ✗ Type error - route doesn't exist
route ( 'invalid.route' );
// ~~~~~~~~~~~~~~
// Argument of type '"invalid.route"' is not assignable to parameter of type 'KnownRouteName'
Strict checking requires generated types. Run php artisan ziggy:generate --types first.
Route Parameters
Required Parameters
TypeScript knows which parameters are required:
// ✓ Valid
route ( 'posts.show' , { post: 1 });
route ( 'posts.show' , [ 1 ]);
route ( 'posts.show' , 1 );
// ✗ Type error - missing required parameter
route ( 'posts.show' );
Optional Parameters
// Both valid
route ( 'posts.index' );
route ( 'posts.index' , { page: 2 });
Multiple Parameters
// All valid formats
route ( 'venues.events.show' , {
venue: 1 ,
event: 2 ,
});
route ( 'venues.events.show' , [ 1 , 2 ]);
Route Model Binding
TypeScript understands custom binding keys:
interface Post {
id : number ;
uuid : string ;
slug : string ;
title : string ;
}
// If route uses 'slug' binding
route ( 'posts.show' , { slug: 'my-post' }); // ✓ Valid
route ( 'posts.show' , post ); // ✓ Also valid - uses binding key from object
Query Parameters
route ( 'posts.index' , {
page: 1 ,
sort: 'desc' ,
});
// Use _query for conflicts
route ( 'venues.events.show' , {
venue: 1 ,
event: 2 ,
_query: {
event: 3 , // Query param with same name as route param
},
});
Framework Integration
Vue 3 with TypeScript
// ziggy-vue.d.ts
import { route as routeFn } from 'ziggy-js' ;
declare module 'vue' {
interface ComponentCustomProperties {
route : typeof routeFn ;
}
}
export {};
Now use route() in templates without errors:
< template >
< a : href = " route ( 'posts.show' , { post: post . id }) " >
{{ post . title }}
</ a >
</ template >
< script setup lang = "ts" >
import { inject } from 'vue' ;
import type { route as routeFn } from 'ziggy-js' ;
interface Post {
id : number ;
title : string ;
}
const route = inject < typeof routeFn >( 'route' ) ! ;
const props = defineProps <{
post : Post ;
}>();
</ script >
React with TypeScript
import React from 'react' ;
import { useRoute } from 'ziggy-js' ;
import type { RouteUrl } from 'ziggy-js' ;
interface Post {
id : number ;
title : string ;
slug : string ;
}
interface PostCardProps {
post : Post ;
}
export default function PostCard ({ post } : PostCardProps ) {
const route = useRoute ();
// Full type safety
const postUrl : RouteUrl = route ( 'posts.show' , { post: post . id });
const editUrl : RouteUrl = route ( 'posts.edit' , { post: post . id });
return (
< article >
< h2 > { post . title } </ h2 >
< a href = { postUrl } > View </ a >
< a href = { editUrl } > Edit </ a >
</ article >
);
}
Complete Example
// types.ts
export interface Post {
id : number ;
uuid : string ;
title : string ;
slug : string ;
body : string ;
author_id : number ;
}
export interface User {
id : number ;
name : string ;
email : string ;
}
// PostsList.tsx
import React , { useState , useEffect } from 'react' ;
import { useRoute } from 'ziggy-js' ;
import type { RouteUrl } from 'ziggy-js' ;
import type { Post } from './types' ;
export default function PostsList () {
const route = useRoute ();
const [ posts , setPosts ] = useState < Post []>([]);
const [ loading , setLoading ] = useState ( true );
useEffect (() => {
async function fetchPosts () {
// TypeScript validates route name and provides autocomplete
const url : RouteUrl = route ( 'api.posts.index' );
const response = await fetch ( url );
const data = await response . json ();
setPosts ( data );
setLoading ( false );
}
fetchPosts ();
}, []);
if ( loading ) return < div > Loading... </ div > ;
return (
< div >
< h1 > Posts </ h1 >
< ul >
{ posts . map (( post ) => {
// TypeScript knows post has id, title, etc.
const postUrl = route ( 'posts.show' , { post: post . id });
return (
< li key = { post . id } >
< a href = { postUrl } > { post . title } </ a >
</ li >
);
}) }
</ ul >
< a href = { route ( 'posts.create' ) } > Create New Post </ a >
</ div >
);
}
Router Class Types
The route() function without arguments returns a typed Router instance:
import { route } from 'ziggy-js' ;
import type { Router } from 'ziggy-js' ;
const router : Router = route ();
// Check current route
const currentRoute : string | undefined = router . current ();
const isPostsIndex : boolean = router . current ( 'posts.index' );
const isPostsRoute : boolean = router . current ( 'posts.*' );
// Check if route exists
const hasRoute : boolean = router . has ( 'posts.show' );
// Get current parameters
const params : Record < string , string > = router . params ;
const routeParams : Record < string , string > = router . routeParams ;
const queryParams : ParsedQs = router . queryParams ;
Type Definitions Reference
Ziggy exports the following types:
import type {
RouteList , // Generated route names and parameters
RouteUrl , // Branded URL string type
Config , // Ziggy configuration object
Router , // Router class interface
TypeConfig , // Configuration for type behavior
} from 'ziggy-js' ;
RouteList
Generated by ziggy:generate --types. Maps route names to their parameter definitions:
export interface RouteList {
'posts.show' : [
{ name : 'post' , required : true , binding ?: 'id' },
];
}
Config
Ziggy’s configuration object structure:
interface Config {
url : string ;
port : number | null ;
defaults : Record < string , string | number >;
routes : Record < string , Route >;
location ?: {
host ?: string ;
pathname ?: string ;
search ?: string ;
};
}
TypeConfig
Extend this to configure Ziggy’s type checking:
declare module 'ziggy-js' {
interface TypeConfig {
strictRouteNames : true ;
}
}
Troubleshooting
Types not showing up
Ensure you’ve generated types: php artisan ziggy:generate --types
Check tsconfig.json includes the generated file
Restart your TypeScript server
”Cannot find module ‘ziggy-js’”
Add a path alias in tsconfig.json:
{
"compilerOptions" : {
"paths" : {
"ziggy-js" : [ "./vendor/tightenco/ziggy" ]
}
}
}
Autocomplete not working
Ensure you’ve generated types and enabled module resolution:
{
"compilerOptions" : {
"moduleResolution" : "node" ,
"esModuleInterop" : true ,
"resolveJsonModule" : true
}
}
“strictRouteNames” not enforcing
Make sure your declaration file:
Uses export {} at the end
Is included in your TypeScript compilation
Comes after generating types
Next Steps
Vue Use Ziggy with Vue and TypeScript
React Use Ziggy with React and TypeScript
Route Helper Learn all route() function capabilities
JavaScript Frameworks Framework integration overview