Try Live
Add Docs
Rankings
Pricing
Docs
Install
Install
Docs
Pricing
More...
More...
Try Live
Rankings
Enterprise
Create API Key
Add Docs
Spatie TypeScript Transformer
https://github.com/spatie/typescript-transformer
Admin
A PHP package that transforms PHP classes and types into TypeScript type definitions.
Tokens:
24,503
Snippets:
136
Trust Score:
8.5
Update:
5 months ago
Context
Skills
Chat
Benchmark
94.1
Suggestions
Latest
Show doc for...
Code
Info
Show Results
Context Summary (auto-generated)
Raw
Copy
Link
# TypeScript Transformer ## Introduction TypeScript Transformer is a PHP library that automatically converts PHP classes, enums, and data transfer objects to TypeScript type definitions. The package analyzes PHP code using reflection to extract type information from properties, methods, and docblocks, then generates corresponding TypeScript types with proper type mappings. This eliminates the need to manually maintain duplicate type definitions across PHP backend and TypeScript frontend codebases. The library uses a plugin-based architecture with transformers, collectors, and type processors that can be customized to handle different PHP structures. It supports attributes and annotations for marking classes as transformable, provides fine-grained control over type conversion through custom transformers, and includes built-in support for common PHP patterns like DTOs, enums, and collections. The generated TypeScript definitions can be exported to a single file and optionally formatted using tools like Prettier. ## Core APIs and Functions ### Basic Configuration and Transformation Configure the transformer with source paths, transformers, and output file, then execute the transformation. ```php use Spatie\TypeScriptTransformer\TypeScriptTransformer; use Spatie\TypeScriptTransformer\TypeScriptTransformerConfig; use Spatie\TypeScriptTransformer\Transformers\MyclabsEnumTransformer; use Spatie\TypeScriptTransformer\Transformers\DtoTransformer; $config = TypeScriptTransformerConfig::create() ->autoDiscoverTypes(__DIR__ . '/src') ->transformers([ MyclabsEnumTransformer::class, DtoTransformer::class, ]) ->outputFile(__DIR__ . '/types.d.ts'); $collection = TypeScriptTransformer::create($config)->transform(); // Output: types.d.ts file created with TypeScript definitions // Returns: TypesCollection with transformed types ``` ### Marking Classes with TypeScript Attribute Mark PHP classes for transformation using the TypeScript attribute with optional custom names. ```php use Spatie\TypeScriptTransformer\Attributes\TypeScript; #[TypeScript] class User { public int $id; public string $name; public ?string $address; } // Generates: // export type User = { // id: number; // name: string; // address: string | null; // } #[TypeScript('CustomUserType')] class User { public int $userId; public string $email; } // Generates: // export type CustomUserType = { // userId: number; // email: string; // } ``` ### DTO Transformation with Complex Types Transform data transfer objects with nested types, arrays, and relationships. ```php use Spatie\TypeScriptTransformer\Attributes\TypeScript; #[TypeScript] class UserDto { public string $name; public int $age; public ?string $email; public AddressDto $address; /** @var string[] */ public array $roles; /** @var TagDto[] */ public array $tags; } #[TypeScript] class AddressDto { public string $street; public string $city; public ?string $zipCode; } #[TypeScript] class TagDto { public string $name; public string $color; } // Generates: // export type AddressDto = { // street: string; // city: string; // zipCode: string | null; // } // // export type TagDto = { // name: string; // color: string; // } // // export type UserDto = { // name: string; // age: number; // email: string | null; // address: AddressDto; // roles: Array<string>; // tags: Array<TagDto>; // } ``` ### Enum Transformation Transform PHP enums to TypeScript union types or native enums. ```php use Spatie\TypeScriptTransformer\Attributes\TypeScript; #[TypeScript] enum Status: string { case PENDING = 'pending'; case APPROVED = 'approved'; case REJECTED = 'rejected'; } $config = TypeScriptTransformerConfig::create() ->autoDiscoverTypes(__DIR__ . '/src') ->transformers([EnumTransformer::class]) ->outputFile(__DIR__ . '/types.d.ts'); // Generates union type (default): // export type Status = 'pending' | 'approved' | 'rejected'; // With native enum option: $config = TypeScriptTransformerConfig::create() ->autoDiscoverTypes(__DIR__ . '/src') ->transformers([EnumTransformer::class]) ->transformToNativeEnums(true) ->outputFile(__DIR__ . '/types.d.ts'); // Generates native TypeScript enum: // export enum Status { // PENDING = 'pending', // APPROVED = 'approved', // REJECTED = 'rejected' // } ``` ### Optional Properties with Attributes Control optional properties using the Optional attribute on properties or entire classes. ```php use Spatie\TypeScriptTransformer\Attributes\TypeScript; use Spatie\TypeScriptTransformer\Attributes\Optional; #[TypeScript] class UserSettings { public string $userId; #[Optional] public string $theme; #[Optional] public int $fontSize; public bool $notificationsEnabled; } // Generates: // export type UserSettings = { // userId: string; // theme?: string; // fontSize?: number; // notificationsEnabled: boolean; // } #[TypeScript] #[Optional] class OptionalConfig { public string $apiKey; public string $endpoint; } // Generates (all properties optional): // export type OptionalConfig = { // apiKey?: string; // endpoint?: string; // } ``` ### Nullable to Optional Conversion Configure nullable properties to be transformed as optional TypeScript properties. ```php use Spatie\TypeScriptTransformer\TypeScriptTransformerConfig; use Spatie\TypeScriptTransformer\Transformers\DtoTransformer; class Profile { public string $name; public ?string $bio; public ?string $website; } // Default behavior (nullable as union with null): $config = TypeScriptTransformerConfig::create() ->autoDiscoverTypes(__DIR__ . '/src') ->transformers([DtoTransformer::class]) ->outputFile(__DIR__ . '/types.d.ts'); // Generates: // export type Profile = { // name: string; // bio: string | null; // website: string | null; // } // With nullToOptional enabled: $config = TypeScriptTransformerConfig::create() ->autoDiscoverTypes(__DIR__ . '/src') ->transformers([DtoTransformer::class]) ->nullToOptional(true) ->outputFile(__DIR__ . '/types.d.ts'); // Generates: // export type Profile = { // name: string; // bio?: string; // website?: string; // } ``` ### Hidden Properties Exclude properties from TypeScript output using the Hidden attribute. ```php use Spatie\TypeScriptTransformer\Attributes\TypeScript; use Spatie\TypeScriptTransformer\Attributes\Hidden; #[TypeScript] class UserAccount { public int $id; public string $username; public string $email; #[Hidden] public string $password; #[Hidden] public string $resetToken; } // Generates: // export type UserAccount = { // id: number; // username: string; // email: string; // } // Note: password and resetToken are excluded ``` ### Custom Type Overrides with TypeScriptType Attribute Override PHP types with custom TypeScript type definitions. ```php use Spatie\TypeScriptTransformer\Attributes\TypeScript; use Spatie\TypeScriptTransformer\Attributes\TypeScriptType; #[TypeScript] class Event { public string $name; #[TypeScriptType('string')] public DateTime $date; #[TypeScriptType('number')] public string $timestamp; #[TypeScriptType(['lat' => 'number', 'lng' => 'number'])] public array $coordinates; #[TypeScriptType('string | number')] public $mixedId; } // Generates: // export type Event = { // name: string; // date: string; // timestamp: number; // coordinates: { // lat: number; // lng: number; // }; // mixedId: string | number; // } ``` ### Default Type Replacements Configure global type replacements for specific PHP classes. ```php use Spatie\TypeScriptTransformer\TypeScriptTransformerConfig; use Carbon\Carbon; use DateTime; use DateTimeImmutable; $config = TypeScriptTransformerConfig::create() ->autoDiscoverTypes(__DIR__ . '/src') ->transformers([DtoTransformer::class]) ->defaultTypeReplacements([ DateTime::class => 'string', DateTimeImmutable::class => 'string', Carbon::class => 'string', 'App\ValueObjects\Money' => 'number', 'App\ValueObjects\Uuid' => 'string', ]) ->outputFile(__DIR__ . '/types.d.ts'); class Order { public DateTime $createdAt; public Carbon $updatedAt; } // Generates: // export type Order = { // createdAt: string; // updatedAt: string; // } ``` ### Custom Collector for Auto-Discovery Create a custom collector to automatically discover and transform classes without annotations. ```php use ReflectionClass; use Spatie\TypeScriptTransformer\Collectors\Collector; use Spatie\TypeScriptTransformer\Structures\TransformedType; use Spatie\TypeScriptTransformer\Transformers\DtoTransformer; class ResourceCollector extends Collector { public function shouldCollect(ReflectionClass $class): bool { return $class->isSubclassOf(Resource::class); } public function getTransformedType(ReflectionClass $class): ?TransformedType { if (!$class->isSubclassOf(Resource::class)) { return null; } $transformer = new DtoTransformer($this->config); return $transformer->transform( $class, str_replace('Resource', '', $class->getShortName()) ); } } // Usage in config: $config = TypeScriptTransformerConfig::create() ->autoDiscoverTypes(__DIR__ . '/src') ->collectors([ResourceCollector::class]) ->transformers([DtoTransformer::class]) ->outputFile(__DIR__ . '/types.d.ts'); // Now all classes extending Resource are automatically transformed: class UserResource extends Resource { public string $name; public string $email; } // Generates: // export type User = { // name: string; // email: string; // } ``` ### Custom Transformer Implementation Build a custom transformer for specialized PHP structures. ```php use ReflectionClass; use Spatie\TypeScriptTransformer\Transformers\Transformer; use Spatie\TypeScriptTransformer\Structures\TransformedType; class CustomDateTransformer implements Transformer { public function transform(ReflectionClass $class, string $name): ?TransformedType { if ($class->getName() !== CustomDate::class) { return null; } $type = <<<TS { year: number; month: number; day: number; isToday: boolean; } TS; return TransformedType::create($class, $name, $type); } } // Register in config: $config = TypeScriptTransformerConfig::create() ->autoDiscoverTypes(__DIR__ . '/src') ->transformers([ CustomDateTransformer::class, DtoTransformer::class, ]) ->outputFile(__DIR__ . '/types.d.ts'); #[TypeScript] class CustomDate { public int $year; public int $month; public int $day; } // Generates: // export type CustomDate = { // year: number; // month: number; // day: number; // isToday: boolean; // } ``` ### Inline Type Definitions Generate inline types that are embedded directly where used instead of separate type definitions. ```php use Spatie\TypeScriptTransformer\Attributes\TypeScript; use Spatie\TypeScriptTransformer\Attributes\InlineTypeScriptType; #[TypeScript] class ApiResponse { public bool $success; public string $message; #[InlineTypeScriptType] public MetaData $meta; } class MetaData { public int $page; public int $total; } // Generates: // export type ApiResponse = { // success: boolean; // message: string; // meta: { // page: number; // total: number; // }; // } // Note: MetaData is inlined instead of being a separate type ``` ### Formatting Output with Prettier Configure automatic formatting of generated TypeScript files. ```php use Spatie\TypeScriptTransformer\TypeScriptTransformerConfig; use Spatie\TypeScriptTransformer\Formatters\PrettierFormatter; $config = TypeScriptTransformerConfig::create() ->autoDiscoverTypes(__DIR__ . '/src') ->transformers([DtoTransformer::class]) ->outputFile(__DIR__ . '/types.d.ts') ->formatter(PrettierFormatter::class); TypeScriptTransformer::create($config)->transform(); // The generated types.d.ts file will be automatically formatted // using Prettier with your project's configuration ``` ### Custom Writer for Output Control Implement a custom writer to control how TypeScript definitions are written to files. ```php use Spatie\TypeScriptTransformer\Writers\Writer; use Spatie\TypeScriptTransformer\Structures\TypesCollection; class CustomWriter implements Writer { public function write(TypesCollection $collection): void { // Group types by namespace $namespaces = []; foreach ($collection as $type) { $namespace = $type->reflection->getNamespaceName(); $namespaces[$namespace][] = $type; } // Write separate files per namespace foreach ($namespaces as $namespace => $types) { $filename = str_replace('\\', '_', $namespace) . '.d.ts'; $content = "// Auto-generated types for {$namespace}\n\n"; foreach ($types as $type) { $content .= "export type {$type->name} = {$type->transformed}\n\n"; } file_put_contents($filename, $content); } } } // Register in config: $config = TypeScriptTransformerConfig::create() ->autoDiscoverTypes(__DIR__ . '/src') ->transformers([DtoTransformer::class]) ->writer(CustomWriter::class); ``` ## Summary and Integration Patterns TypeScript Transformer is designed for modern PHP applications that use TypeScript frontends and need to maintain type safety across the stack. Common use cases include API response type generation for REST or GraphQL APIs, form data types for frontend validation, configuration object types, and event payload types. The library integrates seamlessly with Laravel applications through an Artisan command (`php artisan typescript:transform`) and can be used in any PHP framework or vanilla PHP project through programmatic API calls. The typical integration workflow involves annotating backend classes with `#[TypeScript]` attributes or creating custom collectors for convention-based discovery, configuring transformers for different PHP structures, setting up type replacements for common value objects, and running the transformation as part of the build process. The generated TypeScript definitions can be committed to version control or generated on-demand during CI/CD pipelines. Advanced users can extend the system with custom transformers for domain-specific types, custom collectors for complex discovery patterns, type processors for property-level transformations, and custom writers for specialized output formats. The library's plugin architecture ensures it can adapt to diverse application architectures while maintaining type safety guarantees.