irontec/typescript-generator-bundle
Symfony bundle that generates TypeScript definitions from PHP classes, helping keep backend models and frontend types in sync. Automate interface generation for APIs and DTOs, improve IDE autocomplete, and reduce type duplication. Ideal for Symfony apps needing consistent frontend/backend contracts.
Architecture fit
The package is a build-time codegen utility that bridges Laravel/PHP domain types and a TypeScript front-end contract — a natural fit for Laravel apps using Inertia + Vue/React or a separate SPA consuming an API. The #[TypeScriptMe] PHP attribute is the notable architectural change in 1.0.0: it makes participation opt-in and colocated with the class it describes, which is materially better than config-driven or convention-only generation. It keeps the tool out of the request path, which is the right placement for a type generator.
Integration feasibility Low friction. Composer install, a generator command (now runnable from host or container), and an output directory inside the front-end source tree. Because adoption is per-class via attribute, this can be piloted on one bounded context without touching unrelated code. No runtime dependency is introduced into the application container.
Technical risk Moderate, concentrated in three areas:
TypeScriptBaseInterface fallback for unknown property types, a guard around package.json creation) rather than polish, which suggests the type-mapping surface is still being discovered. Maintainer count, release cadence, and issue responsiveness are unverified.TypeScriptBaseInterface when a property type is unknown is a correctness escape hatch: it prevents generation from failing but can emit a widened/loose contract that silently diverges from the PHP truth. That is the failure mode most likely to reach production, because it fails quietly at the type level rather than loudly at build time.package.json guard). In monorepos or non-standard layouts this can either block generation or target the wrong location.Unverified and material: coverage of backed enums, Collection/array generics, Carbon, Eloquent casts, accessors, and relations; reflection-only vs. schema-aware mapping; namespace/import emission.
Key questions
Carbon to precise TS types, or to widened aliases?package.json location configurable?Stack fit Fits an existing Laravel + TypeScript front-end without restructuring. Container execution is a real operational win: it lets CI and Docker-based dev environments run the generator against a pinned PHP version, avoiding "works on my machine" type output.
Migration path
Incremental and reversible. Start with a single module of DTOs/request payloads, annotate with #[TypeScriptMe], generate into a dedicated directory (e.g. resources/js/types/generated), and consume from there. Expand to Eloquent models only after the type-mapping rules are validated against real cases. Because nothing existing is rewritten, rollback is deleting the annotations and the generated folder.
Compatibility
The attribute is additive, so there is no upgrade cost for current classes. However, the TypeScriptBaseInterface fix means regenerating after upgrade can change the shape of previously generated types for unknown properties — expect a diff in output and treat generated files as reviewable artifacts, not opaque build output. Pin the exact version and diff generated output on every bump.
Sequencing
1.0.0 exactly in composer.json.package.json).Maintenance Low steady-state cost; the tool is a one-shot codegen step, not a runtime component. The maintenance burden is upgrade risk, not operational load: changes to output shape between versions are effectively breaking changes for the front-end even within semver. Mitigate with exact version pinning and generated-output diffs in review.
Support Community open-source with no vendor SLA. This needs a named internal owner and an explicit exit ramp — the fallback is hand-maintained TS types for the annotated surface, which is a bounded, modest cost if adoption is kept scoped. Do not annotate the entire domain model layer before this owner is assigned.
Scaling Generation time scales linearly with annotated class count; fine into the low thousands of classes. Large monorepos may need path scoping to keep runs fast and output isolated per package. Container execution keeps CI consistent as the repo grows.
Failure modes
TypeScriptBaseInterface, producing contracts that compile but don't match PHP. Highest-severity risk; needs a lint/review rule for generated any-adjacent output.package.json guard: generation now aborts if it cannot create package.json. Correct in spirit, but in monorepos where package.json lives at a different level this presents as a hard build break — verify path configuration before CI rollout.Ramp-up Low. The attribute is self-documenting and a mid-level developer can adopt it in an hour. The genuine learning curve is the type-mapping rules and knowing when a fallback has occurred — that knowledge should live with the designated owner rather than be assumed across the team.
How can I help you explore Laravel packages today?