Open cefn opened 2 years ago
@pikax Didn't you work on a PR that made component definition types canonical to enable this kind of usage?
@pikax Didn't you work on a PR that made component definition types canonical to enable this kind of usage?
I did, but I think is different than what's being requested here, I worked on passing props definition to the component, but because of the typescript limitation of not supporting partial typing on generics.
I think this issue is valid we need those helpers to be provided, not sure about the name but don't have a strong opinion
Update: We are still battling with being unable to consistently establish the props of components in our test suites. Is there an option I've missed somewhere?
Within a test we need to be able to author functions that take multiple different components.
For example, our components often need to be tested as a descendant of an ancestor that implements injection, and which has render-exception handling.
The wrap in this ancestor
utility function inevitably accepts a component and its props. However, because of the complexity of Vue component typing, we can't even establish the type of their props from a component definition.
@cefn: Not sure, but maybe volars vue-component-meta can help.
Hey, thanks for the suggestion.
Having looked at it I feel Volar's tooling nature (consuming the source code and reasoning over the abstract syntax tree) makes it quite a different category than type inference. It will introduce substantial complexity and unnecessary failure modes and could certainly never be used at runtime (although my own primary use case is testing, it's true).
We have been using our own pure-typing props inference definition for 6 months or so but it's effective only for our own components and when we start to use a new Vue feature (e.g. emits) then it breaks since the shape we assume when inferring has to be different.
It's for this reason that an inference definition that reflects knowledge of the internal typing design of a Vue component is needed, and having it in the core means it would track changes.
Makes sense. I did some more digging and found this in volar:
export type ComponentProps<T> =
${vueCompilerOptions.strictTemplates ? '' : 'Record<string, unknown> &'}
GlobalAttrs &
ExtractProps<T>;
(source)
export type ExtractProps<T> =
T extends FunctionalComponent<infer P> ? P
: T extends new (...args: any) => { $props: infer Props } ? Props
: T; // IntrinsicElement
(source)
What problem does this feature solve?
Within utilities, it can be useful to be able to type the props of a component. For example, a
@vue/test-utils
mount call could look like this...I successfully established
PropsFor
from a reference toMyComponent
(an example of aDefineComponent
which used the Options API) like this...I feel it's impractical for anyone outside the project to maintain such a definition. Matching one
defineComponent
signature seems brittle and perhaps depends closely on the overload sequence of defineComponent. For example as soon as I moved away from Options API and start usingsetup
to implement MyComponent it seems the above implementation breaks.Also the Vue project may well need to add further
defineComponent
signatures over time and it's infeasible to track these changes.Ideally there would be a canonical representation of
PropsFor
which is maintained within the Vue3 repository, so that you can derive the type of Props given any typed reference to a component.What does the proposed API look like?
...where MyComponent is defined like...