janit/typescript-generator-bundle
A Symfony bundle that generates TypeScript definitions from PHP classes, helping keep frontend and backend types in sync. It automates type generation so TypeScript clients stay aligned with your application models.
Architecture fit. The capability is right; the packaging is wrong for a Laravel shop. janit/typescript-generator-bundle is a Symfony Bundle, not a Laravel package — it registers into a Symfony kernel, wires through Symfony DI, and exposes its logic as a tagged Symfony console command. Laravel has no bundle mechanism and no equivalent auto-registration, so composer require will not yield a usable php artisan command. What is genuinely reusable is the technique: reflect over PHP classes and emit TypeScript interfaces for DTOs, request/response models, and form objects. Treat the repo as a reference implementation and candidate core library, not a dependency. That reframing is the central TPM judgment here, because it determines whether the effort is "a day or two of glue" or "a platform commitment."
Integration feasibility. Two viable paths, and the effort differs by an order of magnitude. (1) Fork/adapt: lift the generator service, discard the Symfony wiring, and re-register behind a single Artisan command in a service provider — roughly one to two days assuming the reflection logic is cleanly separated from the bundle plumbing. (2) Consume a sibling core: bundles of this shape usually wrap a standalone, framework-free generator library, in which case the correct move is to depend on that core directly and write ~100 lines of Artisan glue. Resolve which of these is true before any commitment — it is the single highest-leverage question in this evaluation.
Technical risk. Mostly sustainability, not correctness.
int/float → number, array variance, nullable | null vs optional ?, and generics visible only via docblock parsing. Without a deliberate mapping table the output is lossy and teams patch it by hand, defeating the purpose.Key questions.
src/ layout?.ts files live — committed to the frontend repo, or published as a build artifact?Stack fit. Runtime is PHP (Laravel), frontend is TypeScript. The need — one source of truth for DTO shapes across the boundary — is real and this package addresses it. The fit is indirect: a Symfony-shaped solution to a framework-agnostic problem. Adopt the technique, not the bundle.
Migration path. There is no migration; there is an adoption of the underlying capability.
app/Support/TypeGen, and register one Artisan command — e.g. php artisan types:generate --namespace=App\\Data --out=resources/js/types/generated.ts..ts output, asserted in CI. This is the single most valuable engineering artifact here — it converts an unmaintained dependency into pinned, verifiable behavior.Compatibility. Confirm the fork runs on our exact PHP minor (Laravel 10/11 implies PHP 8.1–8.3) before step 2. If upstream predates enums or readonly classes, patching is likely cheaper than replacing — but budget for it. On the TypeScript side, generated output must satisfy the frontend's strict/noImplicitAny settings; nullable handling that produces implicit any will break the build.
Sequencing. Spike before commitment; extraction and golden-file test as one unit of work; automate last. Do not begin by integrating the Symfony bundle into the Laravel app — that path has no clean endpoint.
Maintenance. The dominant cost, and it lands on us, not the maintainer. Once forked, we own the reflection logic against every PHP upgrade: a few hours per PHP minor plus ad-hoc fixes when a developer hits an unsupported construct. Small but permanent, and it will never appear on a roadmap. Mitigate by keeping the fork thin — glue and a mapping table only — and vendoring the generator core unmodified so upstream fixes can be pulled if they ever arrive.
Support. No vendor, no SLA, no community to escalate to. Internal ownership must be explicit and named; an unowned fork becomes abandoned code within two quarters. Documentation should state plainly: "generated file, do not edit; regeneration command is X."
Scaling. Generation cost is linear in reflected classes — seconds at realistic DTO counts, a non-issue. The real scaling concern is organizational: as DTO volume grows, semantic-mapping edge cases multiply (nested collections, polymorphic payloads, mixed), each a small bespoke decision. Centralize the mapping table so those decisions are reviewable rather than scattered across the codebase.
Failure modes.
.ts stale. Enforce via CI drift check, never by convention.Ramp-up. Low for the concept, moderate for the ownership burden. A mid-level engineer completes the spike and Artisan command in 2–3 days. The substantive ramp is organizational: frontend and backend must agree that generated types are authoritative and hand-edited interfaces are prohibited outside the generated file. Without that agreement, teams maintain parallel hand-written types and the tool becomes pure overhead.
Recommendation. Worth a one-day spike, not worth a direct dependency. The problem is real, the package is the right shape of solution for the wrong framework, and the weak adoption signals mean the durable deliverable is a small, well-tested in-house Artisan command with a golden-file test — using this repo as its starting point and reference.
How can I help you explore Laravel packages today?