isaiasg3/laravel-inertia-type-sync

Automatic End-to-End Type Safety between Laravel (FormRequests/JsonResources) and TypeScript for Inertia.js + Vue 3 apps.
2
Install
composer require isaiasg3/laravel-inertia-type-sync
Latest Version:v1.0.0
PHP:^8.2
License:MIT
Last Updated:Sep 12, 2026
Links: GitHub  ·  Packagist
Maintainer: IsaiasG3

laravel-inertia-type-sync

Latest Version License

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 props or building a useForm().

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 JsonResource without an explicitly declared cast in the corresponding Eloquent model will be generated as unknown.
  • The AST analysis currently only evaluates a top-level return [...] statement inside the toArray() method.

Contributing

Pull Requests are welcome! Please run composer test and composer analyse before submitting your changes.

License

The MIT License (MIT).

Related Packages

oybek-daniyarov/laravel-trpc

End-to-end type-safe APIs for Laravel. Like tRPC, but for Laravel + TypeScript.

274 0
kiwilan/typescriptable-laravel

PHP package for Laravel to type Eloquent models, routes, Spatie Settings with au...

29,884 39
quarc/vue-starter-kit

Quarc Starter Kit - A modern Laravel application starter kit with Vue 3, Inertia...

1 0
jkque/laravel-nuxt-ui-starter-kit

A production-ready Laravel 12 starter kit with Vue 3, Inertia.js v2, Nuxt UI com...

1,233 185