NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
Packagist · #840 most downloaded on Packagist
Transform your PHP structures to TypeScript types
Last release 3 months ago
19 Jun 2026
Release timing varies
gaps range from 2 weeks to 9 months
Nearly every release is documented
notes for 29 of 31 stable releases
Nothing withdrawn
no release was ever pulled
6 years old
32 releases · first in 2020
A round of fixes for the route generator and the typescript:install command.
A round of fixes for the route generator and the typescript:install command.
typescript:install failed for apps created before Laravel 11 that later upgraded, because those apps have no bootstrap/providers.php file and the command assumed it was always present. The command now detects the correct provider registration target instead of relying on that file existing.
Thanks @TheoGibbons.
typescript:install (#89)typescript:install injected the service provider into bootstrap/providers.php with a str_replace anchored on a literal fully qualified class string, so it silently did nothing (while still reporting success) whenever that file used short, imported class names (#86). It now uses Laravel's ServiceProvider::addProviderToBootstrapFile(), which evaluates the file rather than matching raw text and therefore handles every layout, and it reports an honest error when registration is not possible.
The misleading typescript:transform message now points users to typescript:install, and the unreachable namespace rewriting was dropped to keep the command simple.
Thanks @rubenvanassche.
Routes were indexed by controller identity (invokable class, or class@method), so any two routes pointing at the same endpoint overwrote each other and only the last one survived in the generated TypeScript (#87). This silently dropped Route::inertia() pages and the per-locale routes registered by localized routing packages. RouteController::$actions is now a flat list of route bindings instead of a map keyed by method, so the resolver appends every route and the helper emits all named routes.
Thanks @rubenvanassche.
route(), add hasRoute predicate (#85)Calling the generated route() with an unknown name returned the literal string /undefined (an accidental result of '/' + undefined), which silently produced broken URLs in href attributes and elsewhere. route() now throws when the name is not in the manifest, matching Laravel's server-side RouteNotFoundException and surfacing the bug at the call site (spatie/typescript-transformer#151).
A new exported hasRoute(name): name is keyof RouteParameters predicate is emitted alongside route(), mirroring Laravel's Route::has(). It is the safe way to guard the throw for callers that work with dynamic names, such as locale routing wrappers or runtime-composed strings.
// before: could silently produce /undefined
const url = route(maybeName);
// after
if (hasRoute(maybeName)) {
const url = route(maybeName);
}For well-typed TypeScript this is impossible to hit, since the parameter type already constrains the name. Dynamic-name callers should guard with hasRoute() first.
Thanks @rubenvanassche.
route(), add hasRoute predicate by @rubenvanassche in #85Full Changelog: 3.2.0...3.3.0
One column per quarter.
Narrow the controller method type and prioritize HTTP methods
method type and prioritize HTTP methods (#83)Fixes #76. The generated RouteDefinition and MethodRoute types previously declared method: string, which forced casts when handing the result to libraries like Inertia that expect 'get' | 'post' | 'put' | 'patch' | 'delete'. The output now uses a literal union, so:
router.visit(SomeController.update(), { data: { ... } });just works. On top of that, LaravelControllerTransformedProvider accepts a new httpMethodsPriority argument that doubles as both filter and sort order. Methods absent from the list are dropped from the output, and the ones that survive are emitted in list order. The default is ['get', 'post', 'put', 'patch', 'delete'], so HEAD and OPTIONS (auto-registered by Laravel for every GET route, never invoked by SPAs) are no longer emitted.
If you actually relied on the HEAD entries, pass a custom list including 'head'. Thanks @rubenvanassche.
A round of bug fixes for route generation, laravel-data integration, and the writer.
A round of bug fixes for route generation, laravel-data integration, and the writer.
name_mapping_strategy.output config (#81)If your config/data.php looked like this:
'name_mapping_strategy' => [
'output' => SnakeCaseMapper::class,
],The transformer was silently ignoring it and emitting camelCase keys. The processor now resolves property output names through DataConfig::getDataClass(), so the global mapper, class level, and property level MapName / MapOutputName attributes all flow through one source. Thanks @rubenvanassche.
route() helper producing // for the root route (#82)Route::get('/') produced route('home') === '//' because Laravel's $route->uri returns / for the root and bare paths (without a leading slash) for everything else. The runtime helper then prepended another /. After this fix:
route('home'); // '/' (was '//')
route('help.index'); // '/help' (unchanged)Thanks @rubenvanassche.
Watching routes with any RouteFilter configured crashed with Command array element 4 contains a null byte. PHP's serialize() emits \0*\0 markers for protected properties, and Symfony Process rejects command arguments that contain null bytes. Every shipped filter (NamedRouteFilter, ControllerRouteFilter, ClosureRouteFilter) hit this. The serialized payload is now base64 encoded across the process boundary. Thanks @rubenvanassche.
Controller type generation now uses is_a() instead of in_array() when checking for data collection classes, so subclasses of DataCollection are recognised. buildActionCallExpression was also renamed to buildActionCallNode to make it overridable. Thanks @iamrgroot.
GlobalNamespaceWriter producing a broken path when given an absolute path (#79)Passing an absolute path resulted in the output directory being concatenated in front of it:
resources/js/generated/home/user/project/resources/types/generated.d.ts
Pass a relative filename instead, and the writer will resolve it correctly against the configured output directory. Thanks @A909M.
name_mapping_strategy.output config by @rubenvanassche in #81route() helper producing // for the root route by @rubenvanassche in #82GlobalNamespaceWriter producing a broken path when given an absolute path by @A909M in #79Full Changelog: 3.0.3...3.0.4
Fix method name in TypeScriptTransformerServiceProvider configuration by @dominosaurs in #71
Full Changelog: 3.0.2...3.0.3
Full Changelog: https://github.com/spatie/laravel-typescript-transformer/compare/3.0.2...3.0.3
Fixed incorrect namespace and non-existent class in typescript:install command stub
typescript:install command stub (#69)
Spatie\TypeScriptTransformer\Laravel\TypeScriptTransformerApplicationServiceProvider → Spatie\LaravelTypeScriptTransformer\TypeScriptTransformerApplicationServiceProviderNamespaceWriter → GlobalNamespaceWriterFix generic arity mismatch in paginator interface type aliases
This is a major release built on top of the completely rewritten spatie/typescript-transformer v3 .
This is a major release built on top of the completely rewritten spatie/typescript-transformer v3.
spatie/typescript-transformer ^3.0Since it is a complete rewrite, we recommend reading through the new docs and updating your application accodingly.
The first beta release of TypeScript Transformer v3, a complete rewrite from scratch!
The first beta release of TypeScript Transformer v3, a complete rewrite from scratch!
I don't expect that many things will be changing between beta and release but be cautious.
Dropped support for Laravel 8 and 9
fix: don't create a compound type when the type is already a TypeScript type by @Bloemendaal in #53
Full Changelog: 2.5.1...2.5.2
Allow Laravel 12 Full Changelog: https://github.com/spatie/laravel-typescript-transformer/compare/2.5.0...2.5.1
Allow Laravel 12
Full Changelog: https://github.com/spatie/laravel-typescript-transformer/compare/2.5.0...2.5.1
Use service container to resolve TypescriptTransformer by @rasmuscnielsen in https://github.com/spatie/laravel-typescript-transformer/pull/47
nullToOptional by @innocenzi in https://github.com/spatie/laravel-typescript-transformer/pull/46Full Changelog: https://github.com/spatie/laravel-typescript-transformer/compare/2.4.1...2.5.0
Let artisan handle the exceptions by @Tofandel in https://github.com/spatie/laravel-typescript-transformer/pull/41 *
Full Changelog: https://github.com/spatie/laravel-typescript-transformer/compare/2.4.0...2.4.1
- Laravel 11 support Full Changelog: https://github.com/spatie/laravel-typescript-transformer/compare/2.3.2...2.4.0
Full Changelog: https://github.com/spatie/laravel-typescript-transformer/compare/2.3.2...2.4.0
Use Laravel typescript transformer by default
Replace CarbonInterface with a string
Enable collecting of enums by default
Add a native enum transformer by default
Refactor tests to pest by @AyoobMH in https://github.com/spatie/laravel-typescript-transformer/pull/18
Full Changelog: https://github.com/spatie/laravel-typescript-transformer/compare/2.1.6...2.1.7
composer bump for typescript-transformer
do not fail when spatie/enum is not installed
use package service provider to fix publishing config
Nothing published for this version
Nothing published for this version
add support for transforming to native TypeScript enums
fix issue with union types and Laravel collection transformer
Added TypeReflectors to reflect method return types, method parameters & class properties within your transformers
Add support for configuring the writers
- Add support for PHP 8
Moved SpatieEnumTransformer to the typescript-transformer package
SpatieEnumTransformer to the typescript-transformer package- Add support for Laravel 8
- Initial release
Your coding agent can read these notes before it upgrades. Set up the MCP server →