Skip to content

Conversation

pikax
Copy link
Member

@pikax pikax commented May 5, 2020

This improves typing when using

mount({
 props: {
   // ...
  }
})

and also adds the data type validation

const AppWithDefine = defineComponent({
  props: {
    a: {
      type: String,
      required: true
    },
    b: Number
  },
  template: ''
})



// no data provided
expectError(
  mount(AppWithDefine, {
    data() {
      return {
        myVal: 1
      }
    }
  })
)

Copy link
Member

@lmiller1990 lmiller1990 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Asked some questions, this is pretty based

@lmiller1990
Copy link
Member

Maybe @cexbrayat can take a quick look 👀

Copy link
Member

@cexbrayat cexbrayat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like a nice improvement 👍

I added several comments. I think it would be great:

  • to have more tests in mount.d.ts for the functional component and for the data option cases
  • to either simplify the signatures if possible, or comment/test if we can't simplify to explain why

Ping me when you're done and I'll take another look!

src/mount.ts Outdated
ctx: SetupContext
) => RawBindings | RenderFunction,

options: MountingOptions<Props, {}>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: as {} is the default value for the Data type, I think you can simplify to MountingOptions<Props>?

src/mount.ts Outdated
{},
// public props
VNodeProps & Props
>
Copy link
Member

@cexbrayat cexbrayat May 6, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 for handling functional component. Can you add tests in mount.s.ts for this please?

OOC: do we need to declare all the generics here? If we can achieve what we want with just ComponentPublicInstance<Props>? If so, I vote to keep it simple.
If we can't, I would love to:

  • have a comment to explain why
  • have a tsd test that fails without it

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the functional overload can be removed in favour of the

// Functional component
export function mount<
  TestedComponent extends FunctionalComponent<Props>,
  Props
>(
  originalComponent: TestedComponent,
  options?: MountingOptions<Props>
): VueWrapper<ComponentPublicInstance<Props>>

C extends ComputedOptions = {},
M extends Record<string, Function> = {},
E extends EmitsOptions = Record<string, any>,
EE extends string = string
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here: if we really need all the generics, it would be great to have a test showcasing why.
Also, maybe pick more explicit names for the generic types and add comments: I struggle to follow what they refer to

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is basically a copy&paste from defineComponent.ts

To make it simpler to maintain (bring the types from that file), I can add a comment explaining.

mount(AppWithDefine, {
props: { a: 'Hello', b: 2 }
}).vm.a
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I think the test is more readable when splitted like it was. Same for the following changes.

mount(
{
props: ['a']
},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm happy to see that it throws an error, but I don't get how this is different from the test case with AppWithArrayProps which still succeeds? Maybe add more explanation in the comment.
Ideally, shouldn't mount(AppWithArrayProps, { props: { a: 'Hello', b: 2 } }) also fail?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Basically when you use mount({ props: ['a']}) is basically the same as doing defineComponent({props:['a']}), the ThisType will be inferred as the $vm`, resulting in:

mount({
  props: ['a']
})
// type
type MountTyped = {
  props: ['a'] 
} 


const Comp = {
  props: ['a']
}
//type
type CompTyped = {
  props: string[]
}

Basically using mount/defineComponent we maintain the actual tuple value, when using a variable with the options, typescript will resolve the tuple as string[]

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it! So the previous test should also throw if the props were declared as const right?

const AppWithArrayProps = {
  props: ['a'] as const,
  template: ''
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That doesn't seem to happen, if you define as const, it will use props: {} overload 🤔

}
}
})
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 I think more tests with data would be awesome. Can we pass data to all type of components? Can we pass data that are not declared? etc. That will greatly help us maintining the lib if we have extensive coverage of the different cases.

@lmiller1990
Copy link
Member

Is this one awaiting more tests? If so, I can try and help out. LMK where to start - just go over the comments and add those tests?

@cexbrayat
Copy link
Member

@lmiller1990 Yes! I don't know if @pikax had time to start working on them... If not and if you are willing to add some, I'll gladly review them 👍

@lmiller1990
Copy link
Member

lmiller1990 commented May 24, 2020

Have a few other things to work on atm (mainly docs, and vue-jest). If we don't have any bandwidth to add these tests right now, rather than let this PR hang around forever, I'll rebase and get it merged. Is there any must have tests we don't have? We do have some basic ones for mount and shallow.

@lmiller1990
Copy link
Member

Should we merge or do you guys want to add more tests before that?

@lmiller1990
Copy link
Member

I thought about this a bit more. As cool as this feature is, until we have some way to actually get the types from a .vue file, very few people will actually be able to really leverage it. I wonder how difficult this is going to be to get working with vue files 🤔

@cexbrayat
Copy link
Member

I'm OK with merging it. I think it's still better to have it than not, even if I agree with you @lmiller1990

@lmiller1990
Copy link
Member

I think we should definitely have them towards the end of beta and moving into a release candidate - for now I'm happy to merge this up and revisit when we have better IDE integration.

I am really quite excited about this - I know little to nothing about language servers, might be time to learn.

@lmiller1990 lmiller1990 merged commit 1853ec4 into master Jun 1, 2020
@cexbrayat cexbrayat deleted the types/better_mount_object_typing branch April 6, 2022 13:19
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.

3 participants