Search by

isaiasg3 / laravel-inertia-type-sync

IsaiasG3

Automatic End-to-End Type Safety between Laravel (FormRequests/JsonResources) and TypeScript for Inertia.js + Vue 3 apps.

Package info

github.com/IsaiasG3/laravel-inertia-type-sync

pkg:composer/isaiasg3/laravel-inertia-type-sync

Statistics

Installs: 5

Dependents: 0

Suggesters: 0

Stars: 2

Open Issues: 0

v1.0.3 2026-09-12 20:06 UTC

This package is auto-updated.

Last update: 2026-09-12 20:15:42 UTC


README

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).