Require declared block params rather than inferring them #15
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Background
There's been an ongoing conversation around this proto-RFC for formalizing component documentation patterns that includes explicitly providing types for the block parameters a component yields.
As things stand in glint prior to this PR, doing so is possible but not particularly ergonomic:
The only way to accomplish this is by explicitly typing your
template
value, making use of internal knowledge of the signature structure of template invokables and the privateAcceptsBlocks
type. It also doesn't have an obvious analogue for templates defined in accompanying.hbs
files rather than inline.The proposal on the table in that RFC is to add a second type parameter to the base
Component
class that captures the blocks and corresponding parameter types a component intends to yield. This works well from a documentation perspective, but throws a wrench in the current inference-based approach to typing blocks that glint employs.The two options are effectively explicit vs implicit typing for yields, and they can't easily coexist.
This Change
This PR embraces explicit typing for component yields. Aside from working better for documentation purposes, this has several other advantages:
The practical upshot is this: including a
{{yield}}
in a template is now a type error by default, and developers must explicitly provide the expected yields in order for the template to typecheck.Notes
Type Params Form Factor
What I've got here (and what the pre-RFC linked above suggests) has args and yields as two separate type parameters. They could also be combined into a single parameter without impacting anything fundamental about how this works (changes would only be necessary in the environment-specific typings, e.g.
@glint/environment-glimmerx
, nothing deeper).As we look toward the future and additional constraints that it may be useful to capture, it may prove more ergonomic (and easier to expand down the line) to combine these things into a single signature type, along the lines of:
This would make it easier to mix-n-match what information is specified ("this component never yields, but splats its attrs on to an
HTMLTableElement
", or "this takes no args but always yields a string"), which otherwise gets cumbersome with an ever-growing list of positional type params.Further Simplification
Making the signature for a component completely explicit and no longer dependent on the template and/or on inference has the potential to simplify a few other parts of glint in nice (though potentially breaking-change-inducing) ways.
This PR is just the minimal work needed to switch over the core mechanism for typing blocks, and those other simplifications will come as follow-on PRs, likely before I cut an 0.3.0 release.