-
Notifications
You must be signed in to change notification settings - Fork 245
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: split attrs and props mounting options #99
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we have a test with attrs?
I think mentally, users are probably used to having I dont mind, the API change is small, feels clean and looks like it cleans up code as well :) |
This seems fine to me (I didn't even know about the Agree we should add a test for |
@@ -3,8 +3,3 @@ declare module '*.vue' { | |||
import Vue from 'vue' | |||
export default any | |||
} | |||
|
|||
declare module 'vue' { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could use this:
declare module '*.vue' {
import { ComponentOptions } from 'vue'
var component: ComponentOptions
export default component
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code seems fine, can we have a few simple tests in a mountingOptions/attrs.spec.ts
file
This allows a slightly better type checking, even if `defineComponent({ props: { a: String }})` sadly has `$props` typed as `{ a: string } & VNodeProps` and `VNodeProps` allows anything. I'm not sure we can do much on VTU side for now.
I pushed a few simple tests in a new commit and rebased on latest master. I kept the test in |
}) | ||
}) | ||
|
||
test('assigns event listeners', async () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is technically the right way to attach a listener, not through attrs, even though they are identical as of now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So your point is that we should keep the possibility of assigning extra props for this use-case?
There are several options:
- do not allow it as it is in this PR, forcing the user to cast the props as
any
in the test, if he/she really wants to useprops
. I can change the test with a cast to let it in the current file. - allow it, but we lose a it of type safety as we can't make a difference between a badly written prop and an extra prop
- allow it via some other possibility (
mountingProps.extraProps
?) as it is not the most common use-case
What do you think would be the most sound strategy?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So extra props would be attrs basically? If so, then I say just mention in the docs that people can use attrs
for that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, we can nudge the developers in the direction we feel makes more sense in the docs, either:
- use
attrs
for extra props - or use
props
but cast withas any
to indicate this is intentional.
props: { a: 'Hello', b: 2 } | ||
}) | ||
// can't receive extra props | ||
expectError( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would this error out for transparent components without props
defined?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you give me an example of what you mean?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If a component has no props defined, and passes them down via $attrs
.
const Component = {
template: `<div><ChildComponent v-bind="$attrs"/></div>`
}
const wrapper = mount(Component, { props: { a:'a' } })
expect(wrapper.findComponent(ChildComponent).props('a')).toBe('a')
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, so yes: I expect this to error out if the props are not defined (as they end up with the never
type). I think it makes sense to error out, as it is not the most common case, and let the developer use mount(Component, { props: { a:'a' } as any })
in that case. But I'm open to your suggestions if you think this is too constraint.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This wont error out for plain JS use right?
Erroring out is technically wrong, as the Vue API allows you to pass props to that kind of components, but as long as we state the reasoning behind this, should be fine :)
You are right, its not a common use case and having type safety for the 80% of people is better, we just need to make sure these little cases have workarounds for the more novice TS users out there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes this is for TS developers only, JS will be fine, sorry if that wasn't clear :)
And even in TS it still works, it just forces the developers to cast the props
if they want to use it with undeclared props.
IMO, TS developers will be happy to have intellisense/autocomplete/type-checking in tests, and won't be too lost if the compilation indicates that the props does not match the props of the component. But you're 100% right that we need to mention it the docs 👍
@dobromir-hristov I pushed a new commit to reflect our discussion with an example of an explicit cast: it won't get lost in the Github comments ;) |
This allows a slightly better type checking, even if
defineComponent({ props: { a: String }})
sadly has$props
typed as{ a: string } & VNodeProps
andVNodeProps
allows anything. I'm not sure we can do much on VTU side for now.See #90 for context