Weave 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

Typescript Transformer Laravel Package

spatie/typescript-transformer

Convert PHP classes, enums, and DTOs into TypeScript types with spatie/typescript-transformer. It supports complex types, generics, and generated TypeScript functions, making frontend/backend type sharing simple.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit This is a build-time code generation tool, not a runtime library. It occupies the seam between a Laravel/PHP backend and a TypeScript frontend, converting PHP classes, enums, and docblock types into .ts type definitions. That positions it as a contract-enforcement layer: the PHP DTO becomes the single source of truth and the TypeScript type is a derived artifact. Architecturally this is a good fit for teams already treating their API payloads as first-class objects (Form Requests, API Resources, Spatie Data objects), and a poor fit for teams with ad-hoc array payloads, since the tool can only transform what is explicitly modelled.

v3 is a ground-up rewrite with meaningfully better architecture than v2: a real TypeScript AST instead of string concatenation, a visitor pattern for post-processing nodes, TypeScriptReference nodes that resolve imports across files, a TransformedProvider interface for injecting non-PHP-derived types (e.g. framework generics), and a dual writer system (ModuleWriter for one-file-per-type mirroring PHP namespaces, GlobalNamespaceWriter for a single .d.ts). The AST + visitor design is the important one from a TPM perspective: it means generated output can be normalized and linted deterministically, which is what makes a "generated code is committed and CI-enforced" workflow viable.

Integration feasibility Low technical lift to get a first output. composer require spatie/typescript-transformer, publish config, annotate classes, run the command. Feasibility is high for a bounded pilot; the complexity is entirely in the governance around the generated artifacts, not the install.

Things that materially affect feasibility:

  • PHP 8.2+ is mandatory in v3. This is a hard gate and should be checked against the backend's upgrade runway before committing.
  • Type inference now runs on PHPStan's parser rather than PHPDocumentor. This is a genuine improvement (generics, array shapes, key-of/value-of, unions/intersections) but it means the quality of output is directly proportional to the quality of existing docblocks. Sparse annotations produce unknown, not errors.
  • Formatting depends on Node tooling. The Prettier and ESLint formatters shell out via npx. In a PHP-only CI container this either needs Node installed or the formatter step disabled. Not a blocker, but it's a cross-runtime dependency that surprises people.
  • Laravel-specific glue lives in a separate package (laravel-typescript-transformer, referenced as far back as 1.1.0). Confirm the current version pairing before assuming Eloquent/Collection transformations work out of the box.

Technical risk

  • No v2 → v3 upgrade guide. The changelog explicitly states this and recommends reading the docs and upgrading project-by-project. Any team currently on v2 faces effectively a re-implementation: collectors removed, DtoTransformer removed, TypeProcessors replaced by ClassPropertyProcessor, TypeReflectors and inline types removed, two attributes removed. Budget this as a project, not a maintenance task.
  • Historical major-version churn. 2.0 and 3.0 were both breaking; 2.5.0 dropped PHP 8.0. The package moves forward aggressively. Pin the major and treat upgrades as scheduled work.
  • Watch mode is explicitly beta. Do not build developer workflow assumptions on it.
  • Metadata anomaly: the listed last release date (2026-08-28) is in the future, and tracked dependents show as 0. Neither is credible on its face — dependents almost certainly under-reports, and the date suggests scraped or synthetic metadata. Validate real release cadence and Packagist install counts before relying on either signal in a build-vs-adopt decision. Note the low overall score (29.6) against a comparatively high opportunity score (54.5): the opportunity signal reflects a real, underserved problem (PHP↔TS contract drift), while the low score reflects thin observable adoption.
  • Silent degradation is the sharpest product risk. When type resolution fails, output becomes unknown rather than throwing. TypeScript compiles happily against unknown at the consumption site only if consumers narrow it, and in practice consumers cast or ignore it. Every release in the 3.1–3.2 line is a bug fix for exactly this class of failure (inherited @var across namespaces, @template generics resolving to unknown, enum quoting, empty enums being skipped). The failure mode is a quietly weaker contract, not a red build.

Key questions

  1. Is the backend on PHP 8.2+, and is that stable for the next 12–18 months?
  2. Are we greenfield on this tool, or migrating from v2? If v2, what is the actual surface area of custom collectors/DTO transformers?
  3. Which writer strategy fits the frontend — per-module files or one global .d.ts? This decision is expensive to reverse because it changes every import path.
  4. Who owns the generated output — committed to the frontend repo, published as an artifact, or generated inside the frontend build?
  5. Does CI have Node available for formatters, or do we accept unformatted output?
  6. What is the acceptance bar for a generated type — is unknown a pass or a fail? (Recommend: fail.)
  7. Is there an internal owner for custom transformers when defaults don't cover Eloquent models, API Resources, or domain-specific generics?

Integration Approach

Stack fit Natural fit for Laravel + Inertia/Vue/React, Laravel + a separate Next.js/Nuxt SPA, or any PHP backend with a TypeScript consumer. The strongest fit is where payload shape is already modelled as classes (Spatie Data, API Resources, Form Request DTOs) rather than arrays — the tool converts structure that exists, it does not create it. If the backend is annotation-light, front-load a docblock hardening pass; the transformer's output quality is bounded by PHPStan's ability to resolve what's written.

Migration path

  • Greenfield: adopt v3 directly. Do not start on v2 to "play it safe" — the v3 AST/visitor/reference model is the architecture the workflows below depend on.
  • From v2: scope as a rewrite. Inventory every custom collector, DTO transformer, and type processor; each maps to a v3 transformer or property processor, but none map mechanically. Sequence it as an isolated workstream with the old pipeline still producing output until parity is verified by diffing generated files.
  • From nothing (manual .ts types): run in parallel for one cycle. Generate into a scratch directory, diff against hand-written types, and treat every discrepancy as a resolved question about the contract.

Compatibility Verify the full matrix before committing: PHP 8.2+, nikic/php-parser 5, Symfony 7, and the paired laravel-typescript-transformer version. On the consumer side, the output is plain TypeScript — no runtime dependency, no version coupling with the TS toolchain, which is a significant advantage over schema-first alternatives. The only consumer-side coupling is the import path layout implied by the chosen writer.

Sequencing

  1. Inventory and scope. Identify the DTOs that cross the API boundary. Do not attempt whole-codebase transformation — scope to a namespace or a bounded set of resources.
  2. Decide writer strategy and output location. Module writer for modern bundlers with tree-shaking; global .d.ts only for legacy consumers. Lock the output directory — 3.1.1 added a hard exception when it doesn't exist, so wire directory creation into the pipeline explicitly.
  3. Baseline generation. Run defaults, then audit output for unknown and for missing types. This audit is the real cost estimate.
  4. Custom transformers. Add only for genuine gaps (Eloquent models, framework generics) via TransformedProvider rather than post-processing generated text.
  5. CI enforcement. Regenerate in CI and fail on a dirty diff. This is the step that converts the tool from a convenience into a contract guarantee, and it is the step most teams skip.
  6. Formatters. Add Prettier/ESLint formatting at generation time so the diff check is stable across machines. Without a formatter, whitespace churn will make the diff check noisy and teams will disable it.
  7. Watch mode. Offer as an opt-in dev convenience only, clearly labelled beta. Never in CI.

Operational Impact

Maintenance MIT-licensed, Spatie-maintained, active changelog through 3.2.0, with PHPStan and a Pest test suite in CI — good hygiene signals. The maintenance burden shifts from hand-writing TypeScript types to maintaining transformer configuration, custom transformers, and a CI gate. That is a net reduction in ongoing work for a stable DTO surface, and a net increase for a fast-churning one. Budget one part-time owner, not a team.

Support No commercial SLA. Support is GitHub issues plus hosted Spatie docs. For a package on the critical path of a frontend contract, that means the internal team owns first-line support. This is acceptable for a build-time tool — a broken release degrades codegen, not production traffic — which is the single best argument for the risk profile.

Scaling Transformation cost scales roughly linearly with the number of transformed classes; scoping to a namespace keeps CI time bounded. ModuleWriter produces one file per type mirroring PHP namespaces, so file count grows with the domain — fine for bundlers, potentially noisy in review. Large monorepos should scope per-application rather than transforming the whole codebase, both for runtime and to keep the generated diff reviewable. No runtime scaling concerns at all, which is the point.

Failure modes

  • unknown leakage (highest impact). Type resolution fails silently, TypeScript compiles, and the frontend has a weaker contract than it believes. Mitigation: assert against unknown in generated output as a CI check.
  • Silent staleness. Empty enums are skipped (2.4.0) and formatter failures can leave prior output in place. Mitigation: generate into a clean directory each run, then diff.
  • Docblock resolution regressions. Cross-namespace inherited @var and class-level @template both had unknown bugs fixed in 3.1.0/3.2.0. Assume more exist; pin versions and re-audit output on every bump.
  • Formatter availability. npx-based Prettier/ESLint failing in PHP-only containers breaks the pipeline. Mitigation: pin tooling, vendor it, or make formatting a separate gated step.
  • Watch-mode desync (beta). Local definitions drift from PHP while the developer trusts the watcher. Mitigation: keep the CI diff gate authoritative.
  • Major-version cliff. A v4 with breaking changes would strand a v3 pipeline with no upgrade guide, repeating the v2 situation.

Ramp-up Backend developers need very little: install, annotate, run. The real ramp is for whoever writes custom transformers and owns the CI gate — the v3 extension model (AST nodes, visitors, shouldTransform, TransformedProvider, writer configuration) is well-designed but genuinely a new mental model, and there is no upgrade guide to learn from, only the docs. Estimate one engineer for roughly one to two weeks to reach a trustworthy, CI-enforced pipeline for a scoped DTO set, with the majority of that time spent auditing output quality rather than configuring the package. Frontend developers consume plain TypeScript with no new tooling, which keeps the blast radius of the adoption decision contained to one owner on the backend.

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.
roundly-consulting/kubernetes-api-for-laravel
roundly-consulting/plausible-for-laravel
gvp/gvp-laravel-template
metasyncsite/laravel-metasync-client
roundly-consulting/onboarding-for-laravel
andydefer/laravel-notification
adachsoft/cli-process-tester
jhaskell13/laraflow
sebastienheyd/boilerplate-media-manager
ccast/tagixo-primix
pretendtrue/laravel-builder
sawmainek/laravel-scout-tntsearch-driver
tomshaw/laravel-calendar-table
dibakar/laravel-ownership
steadrun/laravel-monitor
labyrinthe/connect-laravel
elmogy/layan
drewdan/sentinel-client
dskripchenko/laravel-llm
fatryst/nuonuo