diephp / laravel-resources-typescript
Generate TypeScript interfaces and type aliases from Laravel JsonResource classes, including enum support
Package info
github.com/diephp/laravel-resources-typescript
pkg:composer/diephp/laravel-resources-typescript
Requires
- php: ^8.1
- nikic/php-parser: ^5.4
Requires (Dev)
- jetbrains/phpstorm-attributes: ^1.0
- laravel/framework: ^9.0 || ^10.0 || ^11.0 || ^12.0 || ^13.0
- phpunit/phpunit: ^10.5 || ^11.5 || ^12.0
Suggests
- laravel/framework: Laravel 9 or newer, only needed for the artisan command and the service provider
README
Laravel Resources to TypeScript
Version 2.0.2 of the package.
Generate TypeScript interface and type definitions from standard Laravel resources without rewriting your API layer into DTO-only abstractions.
The package analyzes native Laravel resources and can extract structure from:
- direct
return []arrays - PHPDoc array shapes
#[ArrayShape(...)]- public typed properties on DTO-style classes
- Eloquent
$fillable toArray()methods that build the response through a variable like$data['field'] = ...; return $data;- resources and fields that return PHP
enum
If a type cannot be determined safely, it falls back to any.
Project Story
This is a lightweight package for development-time generation of TypeScript interfaces from standard Laravel resources for Laravel 9, 10, 11, 12, 13 and PHP 8.1+.
It was originally developed to satisfy a requirement to minimize the use of heavy packages in the Restsify project and then opened for everyone who prefers to keep server resources fully under control.
What's New in 2.0.2
Maintenance release, no API changes and no change to supported Laravel or PHP versions:
- Development constraint for
laravel/frameworkwidened from^9.0to^9.0 || ^10.0 || ^11.0 || ^12.0 || ^13.0, so the test suite can run on any supported framework version instead of an unreleased9.xbranch. minimum-stabilityswitched fromdevtostable, so a plaincomposer updateno longer pulls development branches.jetbrains/phpstorm-attributespinned to a stable^1.0instead ofdev-master.phpunit/phpunitwidened to^10.5 || ^11.5 || ^12.0.- Added a GitHub Actions test matrix (PHP
8.2–8.4) and a Dependabot configuration for dev dependencies.
What's New in 2.0
- Support for PHP
enuminside resources. - Generation of TypeScript
typealiases for PHP enums. - Support for resources that return enum as the root value, not only arrays.
- Better AST analysis for
toArray()methods that build payload through a variable like$data = []; $data['x'] = ...; return $data;. - Support for optional fields created in conditional branches.
- Support for DTO-like classes with public typed properties.
- Recursive scanning of PHP files inside the configured resources directory.
- Cleaner TypeScript output generation with both
interfaceandtype.
Compatibility
- PHP:
^8.1 - Laravel:
9,10,11,12,13— any version that keeps standard resource behaviour - TypeScript output: supports both generated
interfaceandtype
Laravel is not a dependency of this package. The framework is only needed for the artisan command
and the service provider, so it is listed in require-dev (for this repository's own test suite) and
in suggest. Neither of those affects your project: Composer ignores a library's require-dev, so the
package installs next to any Laravel version and never forces an upgrade.
The only production dependency is nikic/php-parser.
Security and dependencies
The package has no runtime dependency on laravel/framework, so no framework advisory can reach a
consumer project through it. Advisories that automated scanners report against this repository refer to
the framework version used by the package's own test suite, not to anything shipped to users.
To keep that noise down without narrowing Laravel support:
require-devspans^9.0through^13.0, so a patched version is always inside the declared range and the repository never pins an end-of-life branch.minimum-stabilityisstable, socomposer updateresolves to real releases instead of adev-masterbranch that the advisory database cannot match.composer.lockis not committed — this is a library, not an application — so no stale locked version can be flagged.- CI runs
composer audit --no-dev, which audits exactly what consumers actually receive.
Upgrading from 1.x
Version 2.0 is mostly source-compatible in usage, but there are a few important changes.
Breaking changes
- Minimum PHP version is now
8.1instead of8.0. - Generated output is no longer limited to
interface. Enum-based definitions can now be emitted as TypeScripttype. - In some resources the generated types may become more precise than in
1.x. For example:- enum fields now reference generated enum types
- conditionally assigned fields can become optional
- DTO public typed properties are now inferred instead of falling back to
any
What remains compatible
- Standard Laravel
JsonResourcewithreturn []. #[ArrayShape(...)].- PHPDoc
@return array{...}. - Nested resources and resource collections.
- Fallback to
anywhen the package cannot safely infer a type.
Installation
composer require --dev diephp/laravel-resources-typescript
For 2.0, your project must run on PHP 8.1+.
Publish the config if you want to customize paths:
php artisan vendor:publish --tag=resources2typescript
Usage
Run the generator:
php artisan diephp:generate-typescript-interfaces
Default config:
'resources_dir' => 'app/Http/Resources', 'output_typescript_file' => 'resources/ts/Resources.ts',
Supported Type Sources
The generator can infer structure from:
- direct
return [] #[ArrayShape(...)]- PHPDoc
@return array{...} - assignments through a temporary variable inside
toArray() - public typed properties on DTO classes
- model PHPDoc properties
- model
$fillable - enum values returned by fields or by the resource itself
Examples
1. Plain resource with casts
class ExampleResource extends JsonResource { public function toArray($request): array { return [ 'id' => (int) $this->id, 'name' => (string) $this->name, ]; } }
export interface ExampleResource { id: number; name: string; }
2. Resource with ArrayShape
use JetBrains\PhpStorm\ArrayShape; class ExampleResource extends JsonResource { #[ArrayShape(['id' => 'int', 'name' => 'string'])] public function toArray($request): array { return [ 'id' => $this->id, 'name' => $this->name, ]; } }
export interface ExampleResource { id: number; name: string; }
3. Resource with PHPDoc array shape
class ExampleResource extends JsonResource { /** * @return array{ * id: int, * name: string, * category: \App\Http\Resources\CategoryResource, * } */ public function toArray($request): array { return [ 'id' => $this->id, 'name' => $this->name, 'category' => new CategoryResource($this->category), ]; } }
export interface ExampleResource { id: number; name: string; category: CategoryResource; }
4. DTO or model-like class with typed public properties
class UserDto { public string $name; public string $email; public int $age; }
export interface UserDto { name: string; email: string; age: number; }
5. Model with PHPDoc properties or $fillable
/** * @property string $domain * @property mixed $protocol */ class SiteModel extends Model { }
class ContactModel extends Model { protected $fillable = ['name', 'email', 'phone']; }
export interface SiteModel { domain: string; protocol: any; } export interface ContactModel { name: any; email: any; phone: any; }
6. Resource built through a variable
class TimeResource extends JsonResource { public function toArray($request): array { $result = []; $result['time'] = $this->resource->time; if ($this->resource->time_zone) { $result['time_zone'] = $this->resource->time_zone; } return $result; } }
export interface TimeResource { time: any; time_zone?: any; }
7. Enum field inside a resource
enum StatusEnum: string { case Draft = 'draft'; case Published = 'published'; } class StatusResource extends JsonResource { public function toArray($request): array { return [ 'status' => StatusEnum::Published, ]; } }
export type StatusEnum = 'draft' | 'published'; export interface StatusResource { status: StatusEnum; }
8. Resource that returns enum as root value
class EnumValueResource extends JsonResource { public function toArray($request) { return StatusEnum::Published; } }
export type EnumValueResource = StatusEnum;
Notes
- Priority is roughly:
ArrayShape-> PHPDoc -> AST analysis oftoArray()-> runtime fallback. - Enum definitions are generated as TypeScript
typealiases. - Nested resources are preserved as references to their generated TypeScript definitions.
- The scanner walks resource directories recursively.
- If the package cannot infer an exact type, it falls back to
any.
Search Keywords
If you are publishing or searching for the package, the main focus of 2.0 is:
- Laravel Resource to TypeScript
- Laravel JsonResource TypeScript generator
- PHP enum to TypeScript
- API resource typings for Laravel
Testing
composer test
Check dependencies against the security advisory database:
composer audit
License
MIT