glint icon indicating copy to clipboard operation
glint copied to clipboard

Infer route model when controller exists

Open simonihmig opened this issue 2 years ago • 5 comments
trafficstars

I was wondering why I was getting Glint errors due to @model being unknown in a route template. After reading https://typed-ember.gitbook.io/glint/using-glint/ember/routes-and-controllers it seems that this is indeed expected, as I have a controller and have not declared the model type there.

After adding something like declare model: Awaited<ReturnType<MyImportedRoute['model']>>; it makes it work!

However I was asking myself if this boilerplate is really needed? Couldn't Glint infer that type automatically, just as it seems to be able to do when no controller exists?

simonihmig avatar Nov 24 '22 18:11 simonihmig

Ultimately this comes down to a design restriction in Glint: a given template only ever has at most 1 backing module, so if a controller exists, we can't then also pull type information from the route. Of course we could loosen that restriction in Glint's internals, but doing so would have the potential to be a pretty complex (and performance intensive) change, as it would essentially mean making the core able to treat arbitrarily-many independent files on disk as somehow composing a single logical module.

Because this only really comes up in this specific situation with route + controller pairs, and because the overall model for routing in Ember is under consideration to be reworked in the near(ish?) future, we haven't gone that route in Glint (pun mostly unintended 🙂)

dfreeman avatar Nov 28 '22 13:11 dfreeman

We have had some fleeting conversations in the past about paving the road a bit better in the Ember types for defining a controller's model field, with potentially some subset/combination of:

  • making Controller<T> parametric on the type of the model field
  • making Controller<T> parametric on the type of the corresponding route
  • exposing a ModelForRoute<T> utility type that abstracts away some of the Awaited<ReturnType<T['model']>> boilerplate

But I don't think anyone had strong enough feelings about what the best path forward there was to make it happen.

dfreeman avatar Nov 28 '22 13:11 dfreeman

One reason that we haven't pushed forward on that is: you can provide a default type parameter for what a Controller<T> is, but there's no way to constrain it to be correct without some manual wiring, courtesy of the convention-based flow that routes and controllers use. And it gets worse: if you happen to use setupController, then using a ModelForRoute utility to define the model prop on the Controller results in circularity in the definitions (playground). 😩

chriskrycho avatar Nov 28 '22 14:11 chriskrycho

Not that I'm necessarily endorsing this approach, but it does seem TS can resolve the circularity if it's plumbed through via a type parameter on the base Controller class https://tsplay.dev/WzaLkm

dfreeman avatar Nov 28 '22 16:11 dfreeman

Oh, that's interesting.


I still don't want it. 😂

chriskrycho avatar Nov 30 '22 02:11 chriskrycho