Skip to content

Resolve @template bindings in Arrayable shapes and Builder method return types - #39

Open
levikl wants to merge 2 commits into
laravel:mainfrom
levikl:template-bindings-via-static-method-dispatch-on-model-subclasses
Open

Resolve @template bindings in Arrayable shapes and Builder method return types#39
levikl wants to merge 2 commits into
laravel:mainfrom
levikl:template-bindings-via-static-method-dispatch-on-model-subclasses

Conversation

@levikl

@levikl levikl commented May 8, 2026

Copy link
Copy Markdown

summary

this change parses and stores @template, @template-covariant, and @template-contravariant docblock tags on ClassLikeResult, giving every analyzed class a typed record of its generic parameters.

e2e flow

given a controller returning Product::paginate(5) inside an Inertia::render() call:

  1. Product::paginate(5) falls back to Builder::paginate() since Product doesn't define it
  2. Builder's ClassLikeResult::templateTags() contains TModel of Model
  3. bindCallerTemplates -> ["TModel" => ClassType(Product)]
  4. substituteInType replaces StringType("TModel") -> ClassType(Product)
  5. result: ClassType(LengthAwarePaginator, genericTypes: [IntType, ClassType(Product)])
  6. ArrayableResolver resolves LengthAwarePaginator::toArray(); data key contains StringType('TKey')|StringType('TValue') placeholders because the Collection::toArray() fast path surfaces them directly from the collection's generic types
  7. substituteTemplateBindings maps TKey -> IntType, TValue -> ClassType(Product)
  8. data: App.Models.Product[] emitted in generated TypeScript

related

merge order

laravel/framework#60045 -> this -> laravel/wayfinder#249

@levikl
levikl force-pushed the template-bindings-via-static-method-dispatch-on-model-subclasses branch 2 times, most recently from 4806783 to a8f16f7 Compare May 8, 2026 05:24
@levikl
levikl force-pushed the template-bindings-via-static-method-dispatch-on-model-subclasses branch from a8f16f7 to 8a6e546 Compare May 8, 2026 06:22
@joetannenbaum

Copy link
Copy Markdown
Collaborator

Thanks for the PR! Is this ready to be looked at? Or is it still a draft?

@levikl
levikl force-pushed the template-bindings-via-static-method-dispatch-on-model-subclasses branch 10 times, most recently from c3b2b1e to 3ef9b16 Compare May 12, 2026 02:54
@levikl levikl changed the title propagate @template bindings through static method dispatch on Model subclasses feat: substitute @template bindings in Arrayable and Builder return type resolution May 12, 2026
@levikl

levikl commented May 12, 2026

Copy link
Copy Markdown
Author

@joetannenbaum yo! saw the direction you're taking with generics in #40 so I went ahead and refactored this to fit naturally alongside it, eg. storing @template declarations from class docblocks in ClassLikeResult and using them to substitute concrete types through Arrayable and Builder return type resolution.

this is ready for review

@levikl
levikl force-pushed the template-bindings-via-static-method-dispatch-on-model-subclasses branch 3 times, most recently from 85c1a4d to eb38770 Compare May 13, 2026 21:08
@levikl levikl changed the title feat: substitute @template bindings in Arrayable and Builder return type resolution Resolve @template bindings in Arrayable shapes and Builder method return types May 13, 2026
@levikl
levikl force-pushed the template-bindings-via-static-method-dispatch-on-model-subclasses branch from eb38770 to 0caa5ec Compare May 13, 2026 21:49
@levikl
levikl force-pushed the template-bindings-via-static-method-dispatch-on-model-subclasses branch 2 times, most recently from fa97a10 to e7ba124 Compare May 15, 2026 04:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants