isaiasg3/laravel-inertia-type-sync
laravel-inertia-type-sync
Automatic End-to-End Type Safety between Laravel and Inertia.js + Vue 3, without any additional PHP annotations.
The Problem
In a typical Inertia.js app, the contract between the backend and frontend lives in two completely separate places that are never validated against each other:
- The
FormRequest::rules()in PHP. - The types (or lack thereof) that the Vue component assumes when receiving
propsor building auseForm().
When someone adds a required field in the backend and forgets to update the frontend (or vice versa), the error only shows up in production, not at compile time. Tools like spatie/laravel-typescript-transformer solve this very well, but they require you to manually annotate every DTO or Resource with PHP attributes.
laravel-inertia-type-sync analyzes your code just as you write it — using Reflection over rules() and AST analysis over toArray() — and generates a single synchronized .d.ts file with a simple Artisan command.
Installation
You can install the package via Composer:
composer require isaiasg3/laravel-inertia-type-sync --dev
Optionally, you can publish the configuration file:
php artisan vendor:publish --tag=inertia-type-sync-config
Check the config/inertia-type-sync.php file to adjust the scanning paths and your models' base namespace if it's different from App\Models.
Usage
Run the following command to generate your types:
php artisan inertia:sync-types
This will generate a file at resources/js/types/generated.d.ts with a TypeScript interface for every FormRequest and JsonResource detected in your project:
export interface StoreUser {
name: string;
email: string;
age?: number | null;
role: 'admin' | 'editor' | 'viewer';
items: Array<{ sku: string; quantity: number }>;
}
export interface UserResource {
id: number;
name: unknown;
is_admin: boolean;
created_at: string;
}
In a Vue 3 component (Composition API)
Forms with useForm — Inertia's generic type validates every v-model against the generated interface:
<script setup lang="ts">
import { useForm } from '@inertiajs/vue3'
import type { StoreUser } from '@/types/generated'
const form = useForm<StoreUser>({
name: '',
email: '',
age: null,
role: 'viewer',
items: [],
})
function submit() {
form.post(route('users.store'))
}
</script>
<template>
<form @submit.prevent="submit">
<input v-model="form.name" type="text" />
<span v-if="form.errors.name">{{ form.errors.name }}</span>
<select v-model="form.role">
<option value="admin">Admin</option>
<option value="editor">Editor</option>
<option value="viewer">Viewer</option>
</select>
</form>
</template>
Typed Props from a JsonResource:
<script setup lang="ts">
import type { UserResource } from '@/types/generated'
const props = defineProps<{ user: UserResource }>()
</script>
<template>
<h1>{{ props.user.name }}</h1>
</template>
Keeping the file synced automatically
Integrate the command into your usual workflow by adding it to your composer.json scripts:
{
"scripts": {
"post-autoload-dump": [
"@php artisan inertia:sync-types --ansi"
]
}
}
This way, every time you run composer dump-autoload or install a new package, your TypeScript types will be automatically updated.
How it works under the hood
| PHP Source | Technique | Result |
|---|---|---|
FormRequest::rules() |
PHP Reflection + rule parser | Interface with primitive types, literal unions (in:), and nested arrays (items.*.sku) |
JsonResource::toArray() |
AST Analysis (nikic/php-parser) over the method's source code |
Interface with types inferred from Eloquent $casts, nested resources, and optional when()/whenLoaded() fields |
Known Limitations
- Properties within a
JsonResourcewithout an explicitly declared cast in the corresponding Eloquent model will be generated asunknown. - The AST analysis currently only evaluates a top-level
return [...]statement inside thetoArray()method.
Contributing
Pull Requests are welcome! Please run composer test and composer analyse before submitting your changes.
License
The MIT License (MIT).
Related Packages
End-to-end type-safe APIs for Laravel. Like tRPC, but for Laravel + TypeScript.
PHP package for Laravel to type Eloquent models, routes, Spatie Settings with au...
Laravel Localizer bridges Laravel translations to your SPA frontend (React/Vue/I...
Quarc Starter Kit - A modern Laravel application starter kit with Vue 3, Inertia...
A production-ready Laravel 12 starter kit with Vue 3, Inertia.js v2, Nuxt UI com...