synergitech/laravel-typescript-generator
最新稳定版本:1.0.0
Composer 安装命令:
composer require synergitech/laravel-typescript-generator
包简介
Generate TypeScript type definitions from Laravel Eloquent models via schema introspection and model metadata.
README 文档
README
Generate TypeScript type definitions from your Laravel Eloquent models automatically. Uses both database schema introspection and model metadata ($casts, $timestamps, etc.) to produce accurate types.
Version Support
| Laravel | PHP | Supported |
|---|---|---|
| 13.x | ^8.3 | ✓ |
| 12.x | ^8.2 | ✓ |
| 11.x | ^8.2 | ✓ |
| 10.x | ^8.1 | ✓ |
Features
- Schema introspection — reads your actual database columns, types, and nullability
- Cast-aware — Laravel
$castsoverride the raw DB type (e.g. ajsoncolumn cast toarraybecomesunknown[]) - Relationship support — optionally include
hasMany,belongsTo, etc. as typed properties - API Resource support — optionally generate types from
JsonResourceclasses (what your API actually returns) - Per-model files — generates one
.d.tsper model plus a barrelindex.d.ts - Configurable — nullable style (
| nullvs?), excluded models, manual type overrides
Installation
composer require synergitech/laravel-typescript-generator
The service provider is auto-discovered by Laravel. No manual registration needed.
Publish the config (optional)
php artisan vendor:publish --tag=typescript-generator-config
This creates config/typescript-generator.php where you can customise everything.
Usage
Basic generation
php artisan types:generate
This scans App\Models, introspects each model's database table, and writes .d.ts files to resources/js/types/.
With relationships
php artisan types:generate --with-relationships
With API resources
php artisan types:generate --with-resources
Resources are off by default. Pass --with-resources (or set include_resources: true in config) to scan App\Http\Resources and generate a .d.ts per resource in resources/js/types/resources/.
Dry run (preview without writing)
php artisan types:generate --dry-run
Example Output
Given a User model with this table:
| Column | Type | Nullable |
|---|---|---|
| id | bigint | no |
| name | varchar(255) | no |
| varchar(255) | no | |
| is_admin | boolean | no |
| metadata | json | yes |
| created_at | timestamp | yes |
| updated_at | timestamp | yes |
And these casts:
protected $casts = [ 'is_admin' => 'boolean', 'metadata' => 'array', ];
The generator produces resources/js/types/User.d.ts:
// Auto-generated by laravel-typescript-generator // Model: App\Models\User // Generated at: 2026-04-08T12:00:00+00:00 export interface User { /** DB: bigint */ id: number; /** DB: varchar | Cast: string */ name: string; /** DB: varchar | Cast: string */ email: string; /** DB: boolean | Cast: boolean */ is_admin: boolean; /** DB: json | Cast: array | nullable */ metadata: unknown[] | null; /** DB: timestamp | nullable */ created_at: string | null; /** DB: timestamp | nullable */ updated_at: string | null; }
Resource output
Given a UserResource that returns:
public function toArray(Request $request): array { return [ 'id' => $this->id, 'name' => $this->name, 'email' => $this->email, 'role' => $this->when($request->user()?->isAdmin(), $this->role), 'address' => new AddressResource($this->address), ]; }
The generator produces resources/js/types/resources/UserResource.d.ts:
// Auto-generated by laravel-typescript-generator // Resource: App\Http\Resources\UserResource import type { AddressResource } from './AddressResource'; export interface UserResource { id: unknown | null; name: unknown | null; email: unknown | null; role?: unknown; address: AddressResource; }
Fields from $this->when(...) whose condition is false at generation time are marked optional (?). Fields whose runtime value is null (empty model attributes) are typed unknown | null. You can refine these with type_overrides in config if needed.
With --with-relationships, if User hasMany Post:
export interface User { // ... attributes ... // Relationships posts?: Post[]; }
Configuration
| Key | Default | Description |
|---|---|---|
model_namespace |
App\Models |
Namespace to scan for models |
model_directory |
app/Models |
Directory path corresponding to the namespace |
output_directory |
resources/js/types/models |
Where model .d.ts files are written |
include_relationships |
false |
Include relationships by default (overridden by CLI flags) |
include_timestamps |
false |
Force-include timestamp columns even if model has $timestamps = false |
nullable_style |
union |
'union' → type | null, 'optional' → type? |
excluded_models |
[] |
FQCNs of models to skip |
type_overrides |
[] |
Manual TS type overrides per model per column |
resource_namespace |
App\Http\Resources |
Namespace to scan for API resources |
resource_directory |
app/Http/Resources |
Directory path corresponding to the resource namespace |
resource_output_directory |
resources/js/types/resources |
Where resource .d.ts files are written |
include_resources |
false |
Generate resource types by default (overridden by CLI flags) |
excluded_resources |
[] |
FQCNs of resources to skip |
Type Overrides Example
// config/typescript-generator.php 'type_overrides' => [ App\Models\User::class => [ 'metadata' => '{ avatar: string; theme: "light" | "dark" }', 'role' => '"admin" | "editor" | "viewer"', ], ],
How Type Resolution Works
For each column the generator applies this priority:
- Manual override (
type_overridesin config) — highest priority - Laravel cast (
$castson the model) — takes precedence over raw DB type - Database column type (via schema introspection) — fallback
This means your casts are always respected. If you cast a json column to array, the TS type will be unknown[], not Record<string, unknown>.
Tip: Add to Your Workflow
Add it to your composer.json scripts so types regenerate after migrations:
{
"scripts": {
"post-migrate": [
"php artisan types:generate"
]
}
}
Or add it to a git pre-commit hook or CI pipeline to keep types in sync.
License
MIT
统计信息
- 总下载量: 3
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 5
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-04-21