diephp/laravel-resources-typescript

Generate TypeScript interfaces and type aliases from Laravel JsonResource classes, including enum support

Maintainers

Package info

github.com/diephp/laravel-resources-typescript

pkg:composer/diephp/laravel-resources-typescript

Transparency log

Statistics

Installs: 265

Dependents: 0

Suggesters: 0

Stars: 3

Open Issues: 1

v2.0.2 2026-08-18 23:21 UTC

This package is auto-updated.

Last update: 2026-08-18 23:21:49 UTC


README

Total Downloads Latest Stable Version License

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/framework widened from ^9.0 to ^9.0 || ^10.0 || ^11.0 || ^12.0 || ^13.0, so the test suite can run on any supported framework version instead of an unreleased 9.x branch.
  • minimum-stability switched from dev to stable, so a plain composer update no longer pulls development branches.
  • jetbrains/phpstorm-attributes pinned to a stable ^1.0 instead of dev-master.
  • phpunit/phpunit widened to ^10.5 || ^11.5 || ^12.0.
  • Added a GitHub Actions test matrix (PHP 8.28.4) and a Dependabot configuration for dev dependencies.

What's New in 2.0

  • Support for PHP enum inside resources.
  • Generation of TypeScript type aliases 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 interface and type.

Compatibility

  • PHP: ^8.1
  • Laravel: 9, 10, 11, 12, 13 — any version that keeps standard resource behaviour
  • TypeScript output: supports both generated interface and type

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-dev spans ^9.0 through ^13.0, so a patched version is always inside the declared range and the repository never pins an end-of-life branch.
  • minimum-stability is stable, so composer update resolves to real releases instead of a dev-master branch that the advisory database cannot match.
  • composer.lock is 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.1 instead of 8.0.
  • Generated output is no longer limited to interface. Enum-based definitions can now be emitted as TypeScript type.
  • 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 JsonResource with return [].
  • #[ArrayShape(...)].
  • PHPDoc @return array{...}.
  • Nested resources and resource collections.
  • Fallback to any when 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 of toArray() -> runtime fallback.
  • Enum definitions are generated as TypeScript type aliases.
  • 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