From Inertia::render() to a page type

From Inertia::render() to a page type

You type your Inertia props by hand. Then a controller changes, and the types drift. Inertia Typegen generates TypeScript types and route helpers for Inertia pages. It reads them from Scramble’s OpenAPI document. You write no types by hand. This post walks from the PHP input to the TypeScript output.

你手动输入 Inertia 的 props。然后控制器发生了变化,类型就会出现偏差。Inertia Typegen 为 Inertia 页面生成 TypeScript 类型和路由助手。它从 Scramble 的 OpenAPI 文档中读取这些信息。你无需手动编写任何类型。本文将介绍从 PHP 输入到 TypeScript 输出的过程。

Install composer require vagebond/inertia-typegen composer require —dev dedoc/scramble Scramble is a development dependency. Inertia Typegen requires PHP 8.3+, Laravel 12 or 13, and Scramble 0.13.49+. It also needs inertia-laravel 2 or 3, Node 22.18+ and Vite 6+.

安装:composer require vagebond/inertia-typegen,composer require --dev dedoc/scramble。Scramble 是一个开发依赖项。Inertia Typegen 需要 PHP 8.3+、Laravel 12 或 13 以及 Scramble 0.13.49+。它还需要 inertia-laravel 2 或 3、Node 22.18+ 和 Vite 6+。

The PHP input Here is a controller with an enum and a paginated resource collection. enum PostStatus: string { case Draft = ‘draft’; case Published = ‘published’; } class PostController { public function index() { return Inertia::render(‘Posts/Index’, [ ‘posts’ => PostResource::collection(Post::paginate()), ‘status’ => PostStatus::Draft, ]); } }

PHP 输入:这是一个包含枚举和分页资源集合的控制器。

enum PostStatus: string { case Draft = 'draft'; case Published = 'published'; } 
class PostController { public function index() { return Inertia::render('Posts/Index', [ 'posts' => PostResource::collection(Post::paginate()), 'status' => PostStatus::Draft, ]); } }

The page type Each Inertia::render() call becomes a page type. The output below is simplified for this post. type PostStatus = ‘draft’ | ‘published’ type PostsIndexProps = SharedData & { // the paginator keeps its real shape posts: PostCollection status: PostStatus }

页面类型:每个 Inertia::render() 调用都会变成一个页面类型。下方的输出为本文进行了简化。

type PostStatus = 'draft' | 'published' 
type PostsIndexProps = SharedData & { // 分页器保持其真实形状
    posts: PostCollection 
    status: PostStatus 
}

Three things happen here. PHP enums become a union of their values. JSON resources, collections and paginators keep their real shape. Shared data from the Inertia middleware becomes one type that each page type includes.

这里发生了三件事。PHP 枚举变成了其值的联合类型。JSON 资源、集合和分页器保持其真实形状。来自 Inertia 中间件的共享数据成为每个页面类型都包含的单一类型。

Form data Form request rules become the type of the form data. class StorePostRequest extends FormRequest { public function rules(): array { return [ ‘title’ => [‘required’, ‘string’], ‘status’ => [‘required’, Rule::enum(PostStatus::class)], ]; } } type StorePostData = { title: string status: PostStatus }

表单数据:表单请求规则成为表单数据的类型。

class StorePostRequest extends FormRequest { public function rules(): array { return [ 'title' => ['required', 'string'], 'status' => ['required', Rule::enum(PostStatus::class)], ]; } } 
type StorePostData = { title: string status: PostStatus }

You change a rule in PHP. The form type follows.

你在 PHP 中更改了一条规则,表单类型也会随之更新。

Route helpers You also get typed route helpers for each named route.

路由助手:你还可以为每个命名路由获得类型化的路由助手。

Keeping files fresh The Vite dev server regenerates files after a PHP change. A CI check fails when committed files are stale. You commit the generated files, so a production build needs no PHP. No HTTP endpoint is added by default. Plugins with hooks can change the document, routes and output.

保持文件更新:Vite 开发服务器会在 PHP 更改后重新生成文件。当提交的文件过时时,CI 检查会失败。你提交生成的文件,因此生产构建不需要 PHP。默认情况下不会添加 HTTP 端点。带有钩子的插件可以更改文档、路由和输出。

The limit The release status is 0.x. Minor releases can contain breaking changes until 1.0. So pin the minor version and check each upgrade. Inertia Typegen is MIT licensed. The docs cover setup, route helpers and plugins: https://baken.vagebond.nl/r/dpRMA9Ze

限制:发布状态为 0.x。在 1.0 版本之前,次要版本可能包含重大更改。因此,请锁定次要版本并检查每次升级。Inertia Typegen 采用 MIT 许可。文档涵盖了设置、路由助手和插件:https://baken.vagebond.nl/r/dpRMA9Ze