Skip to content

Type error with functional component #1781

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

Closed
yshrsmz opened this issue Feb 1, 2021 · 2 comments · Fixed by #1789
Closed

Type error with functional component #1781

yshrsmz opened this issue Feb 1, 2021 · 2 comments · Fixed by #1789

Comments

@yshrsmz
Copy link
Contributor

yshrsmz commented Feb 1, 2021

Subject of the issue

Describe your issue here.

Wrapper and mount/shallowMount do not support functional components defined with Vue.extend()

Steps to reproduce

Tell us how to reproduce this issue. Please provide a working and simplified example.

// test.ts
import Vue, { CreateElement, VNode, RenderContext } from 'vue'

export default Vue.extend({
  name: 'Test',
  functional: true,
  render(createElement: CreateElement, context: RenderContext): VNode {
    return createElement('span', context.data, ['test'])
  },
})
import { RouterLinkStub, shallowMount, mount, Wrapper } from '@vue/test-utils'
import Test from './test'

describe('test', () => {
  // error 1
  let wrapper: Wrapper<Test>

  beforeEach(() => {
    wrapper = mount(Test, {
      context: {
        props: {},
        // error 2
        children: []
      }
    })
  })
})

Error 1

'Test' refers to a value, but is being used as a type here. Did you mean 'typeof Test'?

Error 2

No overload matches this call.
  Overload 1 of 3, '(component: VueClass<CombinedVueInstance<Record<string, any> & Vue, object, object, object, Record<never, any>>>, options?: ThisTypedMountOptions<...> | undefined): Wrapper<...>', gave the following error.
    Type '{ props: {}; children: never[]; }' is not assignable to type 'VNodeData'.
      Object literal may only specify known properties, and 'children' does not exist in type 'VNodeData'.
  Overload 2 of 3, '(component: ComponentOptions<any, DefaultData<any>, DefaultMethods<any>, DefaultComputed, PropsDefinition<Record<string, any>>, Record<...>>, options?: ThisTypedMountOptions<...> | undefined): Wrapper<...>', gave the following error.
    Type 'VueConstructor<Record<string, any> & Vue>' has no properties in common with type 'ComponentOptions<any, DefaultData<any>, DefaultMethods<any>, DefaultComputed, PropsDefinition<Record<string, any>>, Record<...>>'.
  Overload 3 of 3, '(component: FunctionalComponentOptions<Record<string, any>, PropsDefinition<Record<string, any>>>, options?: MountOptions<Vue> | undefined): Wrapper<...>', gave the following error.
    Argument of type 'ExtendedVue<Vue, {}, {}, {}, Record<string, any>>' is not assignable to parameter of type 'FunctionalComponentOptions<Record<string, any>, PropsDefinition<Record<string, any>>>'.ts(2769)

Expected behaviour

It should compile and work fine without any error.

Actual behaviour

descried above.

Possible Solution

When I change let wrapper: Wrapper<Test> to let wrapper: Wrapper<typeof Test>, it then shows a different error.

No overload matches this call.
  Overload 1 of 3, '(component: VueClass<CombinedVueInstance<Record<string, any> & Vue, object, object, object, Record<never, any>>>, options?: ThisTypedMountOptions<...> | undefined): Wrapper<...>', gave the following error.
    Type '{ props: {}; children: never[]; }' is not assignable to type 'VNodeData'.
      Object literal may only specify known properties, and 'children' does not exist in type 'VNodeData'.
  Overload 2 of 3, '(component: ComponentOptions<Vue, DefaultData<Vue>, DefaultMethods<Vue>, DefaultComputed, PropsDefinition<Record<string, any>>, Record<...>>, options?: ThisTypedMountOptions<...> | undefined): Wrapper<...>', gave the following error.
    Type 'VueConstructor<Record<string, any> & Vue>' has no properties in common with type 'ComponentOptions<Vue, DefaultData<Vue>, DefaultMethods<Vue>, DefaultComputed, PropsDefinition<Record<string, any>>, Record<...>>'.
  Overload 3 of 3, '(component: FunctionalComponentOptions<Record<string, any>, PropsDefinition<Record<string, any>>>, options?: MountOptions<Vue> | undefined): Wrapper<...>', gave the following error.
    Argument of type 'ExtendedVue<Vue, {}, {}, {}, Record<string, any>>' is not assignable to parameter of type 'FunctionalComponentOptions<Record<string, any>, PropsDefinition<Record<string, any>>>'.ts(2769)

It seems like mount and shallowMount methods work with functional components without Vue.extend(), but does not with Vue.extend()

@yshrsmz
Copy link
Contributor Author

yshrsmz commented Feb 1, 2021

versions

vue: 2.6.12
@vue/test-utils: 1.1.2
typescript: 4.0.5

@lmiller1990
Copy link
Member

Primarily a typing issue, correct?

The types here are really not idea; both Vue 2 and the types here are written manually, so they have some problems. Are you interested in submitting a PR to fix this?

I am guessing the work around for issue 2 is something like mount(Test, {...} as any).

yshrsmz added a commit to yshrsmz/vue-test-utils that referenced this issue Feb 15, 2021
add mount & shallowMount type definitions for ExtendedVue, return type of Vue.extend() method

this fixes vuejs#1781
yshrsmz added a commit to yshrsmz/vue-test-utils that referenced this issue Feb 15, 2021
add mount & shallowMount type definitions for ExtendedVue, return type of Vue.extend() method

this fixes vuejs#1781
lmiller1990 pushed a commit that referenced this issue Feb 24, 2021
add mount & shallowMount type definitions for ExtendedVue, return type of Vue.extend() method

this fixes #1781
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants