Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Typescript Transformer Laravel Package

spatie/laravel-typescript-transformer

Convert PHP classes, enums, and more into TypeScript types automatically in Laravel. Mark PHP code with attributes, handle complex types and generics, and generate TS-friendly definitions (and even functions) to keep frontend types in sync.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require spatie/laravel-typescript-transformer
    php artisan vendor:publish --provider="Spatie\LaravelTypeScriptTransformer\TypeScriptTransformerServiceProvider"
    

    This publishes the service provider stub to app/Providers/TypeScriptTransformerServiceProvider.php.

  2. Basic Usage: Add the #[TypeScript] attribute to any PHP class to generate TypeScript types:

    use Spatie\LaravelTypeScriptTransformer\Attributes\TypeScript;
    
    #[TypeScript]
    class User {
        public int $id;
        public string $name;
    }
    

    Run the transformer:

    php artisan typescript:transform
    

    Output will be generated in resources/js/types.

  3. First Use Case: Transform a DTO or model to TypeScript for frontend API contracts. Example:

    #[TypeScript]
    class CreateUserRequest {
        public string $name;
        public ?string $email = null;
        public array $roles = [];
    }
    

    Generates:

    export type CreateUserRequest = {
        name: string;
        email: string | null;
        roles: string[];
    }
    

Implementation Patterns

Core Workflows

  1. Class/Enum Transformation:

    • Annotate classes/enums with #[TypeScript] to auto-generate types.
    • Customize output with attributes like #[TypeScript(name: "CustomName")].
  2. Controller/Route Generation:

    • Generate typed route helpers and controller action signatures:
      #[TypeScript]
      class UserController {
          public function store(StoreUserRequest $request): UserResource { ... }
      }
      
      Outputs:
      export type UserController = {
          store: (request: StoreUserRequest) => UserResource;
      };
      
  3. Watch Mode: Enable real-time updates during development:

    php artisan typescript:watch
    

    Automatically regenerates types on file changes.

  4. Custom Transformers: Extend default behavior by creating custom transformers:

    use Spatie\TypeScriptTransformer\Transformers\Transformer;
    
    class CustomTransformer extends Transformer {
        public function transform($value): string {
            return 'CustomType';
        }
    }
    

    Register in TypeScriptTransformerServiceProvider.

Integration Tips

  • Frontend Integration: Place generated types in resources/js/types and import them in your frontend framework (Vue/React). Example:

    import type { User } from '@/types/User';
    
  • API Contracts: Use for OpenAPI/Swagger documentation or frontend validation (e.g., with Zod).

  • Laravel Collections: Transform collections to typed arrays:

    #[TypeScript]
    class UserCollection extends Collection {
        public function toTypeScript(): string {
            return $this->map(fn ($user) => $user->toTypeScript())->implode(', ');
        }
    }
    
  • Dynamic Types: Generate types for database queries or Eloquent models:

    #[TypeScript]
    class UserModel extends Model {
        protected $fillable = ['name', 'email'];
    }
    

Gotchas and Tips

Pitfalls

  1. Namespace Conflicts:

    • Ensure generated TypeScript files don’t collide with existing files. Use #[TypeScript(name: "CustomName")] to override names.
    • Example:
      #[TypeScript(name: "UserDto")]
      class User { ... }
      
  2. Circular Dependencies:

    • Avoid circular references between transformed classes (e.g., User referencing Profile which references User). Use #[TypeScript(ignore: true)] or flatten structures.
  3. PHP 8.2+ Requirement:

    • The package requires PHP 8.2+ and Laravel 10+. Downgrade if using older versions (use v2.x).
  4. Watch Mode Quirks:

    • Exclude node_modules or vendor from watch patterns in typescript-transformer.php:
      'watch' => [
          'paths' => ['app/Models', 'app/Dtos'],
          'ignore' => ['node_modules', 'vendor'],
      ],
      
  5. Enum Handling:

    • Native PHP enums are converted to TypeScript union types by default. For custom behavior, implement a Transformer for Spatie\TypeScriptTransformer\Transformers\EnumTransformer.

Debugging

  • Verbose Output: Enable debug mode in the service provider:

    $this->app->singleton(TypeScriptTransformer::class, fn () => new TypeScriptTransformer(
        debug: true
    ));
    

    Logs transformation steps to storage/logs/laravel.log.

  • Type Mismatches: If types don’t match expectations, inspect the raw PHP structure with:

    php artisan typescript:inspect App\Models\User
    
  • Cache Issues: Clear the TypeScript cache after changes:

    php artisan typescript:clear
    

Extension Points

  1. Custom Writers: Override the default file writer to output types to a custom location or format:

    $this->app->singleton(Writer::class, fn () => new CustomWriter(
        path: storage_path('app/types'),
        formatter: new PrettierFormatter()
    ));
    
  2. TypeScript Formatting: Integrate Prettier or ESLint for consistent formatting:

    use Spatie\TypeScriptTransformer\Formatters\PrettierFormatter;
    
    $this->app->singleton(Formatter::class, fn () => new PrettierFormatter());
    
  3. Dynamic Type Generation: Generate types at runtime for dynamic queries:

    $transformer = app(TypeScriptTransformer::class);
    $type = $transformer->transform(new User());
    
  4. Excluding Classes: Skip specific classes with:

    #[TypeScript(ignore: true)]
    class ExcludedClass { ... }
    

    Or globally in the service provider:

    'ignore' => [
        'App\\Models\\Excluded*',
    ],
    
  5. Handling Laravel-Specific Types: Customize transformations for Laravel collections, paginators, or Eloquent models by extending:

    class LaravelCollectionTransformer extends Transformer {
        public function transform(Collection $collection): string {
            return 'Array<' . $collection->first()->toTypeScript() . '>';
        }
    }
    

    Register in the service provider:

    $this->app->singleton(Transformer::class, fn () => new LaravelCollectionTransformer());
    

Pro Tips

  • TypeScript Interfaces vs. Types: Use #[TypeScript(as: 'interface')] to generate interfaces instead of types:

    #[TypeScript(as: 'interface')]
    class User { ... }
    

    Outputs:

    export interface User { ... }
    
  • Union Types: Transform nullable or union properties automatically:

    public ?string $name; // => string | null
    public int|string $id; // => number | string
    
  • Generics Support: Handle generic classes:

    #[TypeScript]
    class ApiResponse<T> {
        public T $data;
    }
    

    Outputs:

    export type ApiResponse<T> = {
        data: T;
    };
    
  • Inline Types: Generate types inline for one-off usage:

    $transformer = app(TypeScriptTransformer::class);
    $type = $transformer->transform(new User());
    echo "type UserInline = {$type};";
    
  • Testing: Mock the transformer in tests:

    $transformer = Mockery::mock(TypeScriptTransformer::class);
    $transformer->shouldReceive('transform')
        ->with(new User())
        ->andReturn('type User = { ... }');
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport