oi-lab/oi-laravel-ts
Generates TypeScript interfaces from Laravel Eloquent models, including relationships, casts, PHPDoc types, and DataObjects. Supports watch mode, namespace filtering, UUID/ULID key typing, and optional JSON-LD output.
Installation:
composer require oi-lab/oi-laravel-ts
php artisan vendor:publish --tag=oi-laravel-ts-config
First Run:
php artisan oi:gen-ts
resources/js/types/interfaces.ts by default.app/Models for Eloquent models.Quick Use Case:
User with relationships (e.g., hasMany(Post)).IUser with typed relationships:
export interface IUser {
id: number;
posts?: IPost[];
}
Model Definition:
// app/Models/User.php
class User extends Model {
public function posts(): HasMany { return $this->hasMany(Post::class); }
}
Generate Interfaces:
php artisan oi:gen-ts
Use in TypeScript:
import { IUser } from '@/types/interfaces';
const user: IUser = await fetchUser();
Watch Mode (auto-regenerate on model changes):
php artisan oi:gen-ts --watch
Custom Properties (add non-database fields):
// config/oi-laravel-ts.php
'custom_props' => [
'User' => [
'full_name' => 'string',
'avatar_url' => 'string',
],
],
DataObject Support (auto-generate interfaces for cast value objects):
// app/Models/Page.php
protected $casts = ['metadata' => MetadataCast::class];
Outputs:
export interface IMetadata { title: string; }
export interface IPage { metadata?: IMetadata; }
Inertia.js: Type page props with generated interfaces:
interface DashboardProps extends PageProps {
user: IUser;
}
API Responses: Use interfaces for request/response validation (e.g., with zod or class-validator).
Namespace Conflicts:
excluded_namespaces to avoid bloated schemas.'excluded_namespaces' => ['Spatie\\Permission\\Models'],
UUID/ULID Keys:
HasUuids or $keyType = 'string' generate id: string (not number).'save_schema' => true in config to inspect intermediate output.Circular Dependencies:
User ↔ Post) may cause infinite loops.'discover_related_models' => false to limit scope or manually configure extended_namespaces.'save_schema' => true to inspect raw model data before TypeScript conversion.Custom Type Mappings:
// config/oi-laravel-ts.php
'props_with_types' => [
'App\\Models\\User' => [
'email_verified_at' => 'Date',
],
],
External Imports:
'custom_props' => [
'User' => [
'settings' => '@/types/settings|UserSettings',
],
],
Outputs:
import { UserSettings } from '@/types/settings';
Multi-File Output:
--multi-file flag to generate one file per interface + an index.ts barrel.@property or @method in models for finer control over generated types.'with_json_ld' => true for structured data APIs.Model::when() in a custom discovery class.How can I help you explore Laravel packages today?