Laravel dan TypeScript Sinkron Otomatis Pakai Data Object Spatie
Tim Spatie punya cara untuk berhenti menyamakan tipe data Laravel dan TypeScript secara manual, yaitu lewat spatie/laravel-data dan spatie/laravel-typescript-transformer. Class PHP jadi sumber kebenaran, lalu definisi TypeScript dibuat otomatis dari situ. Cara ini mereka pakai di There There, helpdesk yang sedang mereka kembangkan.
Latar belakangnya begini. Spatie membangun aplikasi SaaS dengan Laravel di backend dan Inertia dengan React di frontend, sehingga dua sistem tipe harus sepakat soal setiap payload yang lewat di antaranya. Di There There, tiket, pesan, member, sampai section sidebar kustom semuanya melewati jembatan itu. Merawat semua tipenya dengan tangan jelas bikin pusing, jadi mereka mengotomatiskannya. There There sendiri saat ini masih private beta.
Dari class Data ke definisi TypeScript
Sebuah payload dimulai sebagai class Data. Contohnya MemberData, yang dikirim setiap kali halaman detail member dirender. Isinya properti constructor seperti id, ulid, name, email, avatar_url yang nullable, role berupa enum WorkspaceMemberRole, joined_at, dan restricted_channel_access yang bernilai false secara default. Atribut #[TypeScript] berfungsi sebagai penanda opt-in: class PHP mana pun yang membawanya akan diambil oleh transformer.
Transformer-nya sendiri adalah package Laravel biasa dengan file konfigurasi. Ada tiga bagian yang perlu kamu perhatikan:
- auto_discover_types memindai folder app/ untuk mencari class yang diberi anotasi.
- transformers menangani data class, DTO, enum, dan state machine Spatie.
- default_type_replacements menukar tipe PHP dengan padanannya di TypeScript. Dengan cara ini, setiap tanggal Carbon menjadi string biasa di frontend.
Hasilnya ditulis ke resources/js/types/generated.d.ts. Untuk MemberData, outputnya berupa type dengan field yang persis mengikuti constructor, misalnya avatar_url bertipe string | null. Namespace-nya mencerminkan namespace PHP, dan enum dirujuk ke tipe hasil generate-nya sendiri. Jadi kalau kamu mengganti nama case enum di PHP, perubahannya ikut sampai ke setiap pemanggil di TypeScript.
Update tipe otomatis lewat Vite
Kamu bisa membuat ulang file tersebut secara manual dengan php artisan typescript:transform. Tim Spatie memilih menyambungkannya ke Vite lewat plugin kustom kecil. Saat dev server berjalan dan ada file PHP di folder Data/ atau Enums/ yang berubah, hook handleHotUpdate menjalankan php artisan typescript:transform, sehingga tipe di frontend langsung diperbarui. Tidak ada langkah manual dan tidak ada definisi usang.
Di spatie/laravel-typescript-transformer v3, ada opsi yang lebih sederhana: mode watch bawaan. Setelah chokidar terpasang, jalankan php artisan typescript:transform --watch. Spatie masih memakai v2.6, yang belum punya opsi --watch, jadi plugin Vite tadi yang bertugas menangkap perubahan.
Menurut tim Spatie, setup ini menghapus satu kategori masalah kecil yang mengganggu. Kalau mereka mengganti nama properti PHP, compiler TypeScript langsung menandai semua pemanggil di frontend. Kalau mereka menambah field, field itu muncul di autocomplete dalam hitungan detik. Bagi kamu yang memakai kombinasi Laravel dan Inertia dengan React, pola ini bisa ditiru langsung, dan kalau kamu memakai v3, mode watch bawaannya membuat konfigurasinya lebih ringkas.