Skip to content
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

fix(types): component instance inference without props #2145

Merged

Conversation

@antfu antfu changed the title bug(types): component instance does not get proper type inference without props fix(types): component instance inference without props Sep 18, 2020
@antfu antfu marked this pull request as ready for review September 18, 2020 03:39
@yyx990803 yyx990803 merged commit 57bdaa2 into vuejs:master Sep 18, 2020
@shrink
Copy link

shrink commented Sep 20, 2020

Hi @antfu! I'm working through an issue that has appeared when upgrading from a release candidate (8) to the release of Version 3.0.0. As far as I can tell, I've tracked down the issue to this PR: I'm using the HelloWorld component favoured in many of the VueJS examples:

<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
  </div>
</template>

<script lang="ts">
import { defineComponent } from 'vue';

export default defineComponent({
  name: 'HelloWorld',
  props: {
    msg: String,
  },
});
</script>

And then I have a simple test, also sourced from a guide:

describe('HelloWorld.vue', () => {
  it('renders props.msg when passed', () => {
    const msg = 'new message';
    const wrapper = shallowMount(HelloWorld, {
      props: { msg },
    });
    expect(wrapper.text()).toMatch(msg);
  });
});

This test passed successfully before the final release but I'm now seeing the following error:

TypeScript diagnostics (customize using `[jest-config].globals.ts-jest.diagnostics` option):
    tests/unit/example.spec.ts:7:34 - error TS2769: No overload matches this call.
      The last overload gave the following error.
        Argument of type 'DefineComponent<readonly string[] | Readonly<ComponentObjectPropsOptions<Record<string, unknown>>>, unknown, unknown, Record<string, ComputedGetter<any> | WritableComputedOptions<...>>, ... 7 more ..., { ...; } | {}>' is not assignable to parameter of type 'ComponentOptionsWithObjectProps<readonly string[] | Readonly<ComponentObjectPropsOptions<Record<string, unknown>>>, unknown, unknown, Record<string, ComputedGetter<any> | WritableComputedOptions<...>>, ... 6 more ..., { ...; } | {}>'.
          Type 'DefineComponent<readonly string[] | Readonly<ComponentObjectPropsOptions<Record<string, unknown>>>, unknown, unknown, Record<string, ComputedGetter<any> | WritableComputedOptions<...>>, ... 7 more ..., { ...; } | {}>' is not assignable to type 'ComponentOptionsBase<Readonly<{ [x: number]: string; } & { length?: number | undefined; toString?: string | undefined; toLocaleString?: string | undefined; concat?: string[] | undefined; join?: string | undefined; ... 17 more ...; flat?: unknown[] | undefined; }> | Readonly<...>, ... 8 more ..., { ...; } | {}>'.
            Types of property 'setup' are incompatible.
              Type '((this: void, props: Readonly<{ [x: number]: string; } & { length?: number | undefined; toString?: string | undefined; toLocaleString?: string | undefined; concat?: string[] | undefined; join?: string | undefined; ... 17 more ...; flat?: unknown[] | undefined; }> | Readonly<...>, ctx: import("/app/node_modules/@vue/...' is not assignable to type '((this: void, props: Readonly<{ [x: number]: string; } & { length?: number | undefined; toString?: string | undefined; toLocaleString?: string | undefined; concat?: string[] | undefined; join?: string | undefined; ... 17 more ...; flat?: unknown[] | undefined; }> | Readonly<...>, ctx: import("/app/node_modules/@vue/...'. Two different types with this name exist, but they are unrelated.
                Type '(this: void, props: Readonly<{ [x: number]: string; } & { length?: number | undefined; toString?: string | undefined; toLocaleString?: string | undefined; concat?: string[] | undefined; join?: string | undefined; slice?: string[] | undefined; ... 16 more ...; flat?: unknown[] | undefined; }> | Readonly<...>, ctx: im...' is not assignable to type '(this: void, props: Readonly<{ [x: number]: string; } & { length?: number | undefined; toString?: string | undefined; toLocaleString?: string | undefined; concat?: string[] | undefined; join?: string | undefined; slice?: string[] | undefined; ... 16 more ...; flat?: unknown[] | undefined; }> | Readonly<...>, ctx: im...'. Two different types with this name exist, but they are unrelated.
                  Types of parameters 'ctx' and 'ctx' are incompatible.
                    Type 'SetupContext<string[]>' is not assignable to type 'SetupContext<EmitsOptions>'.
                      Type 'EmitsOptions' is not assignable to type 'string[]'.
                        Type 'Record<string, ((...args: any[]) => any) | null>' is missing the following properties from type 'string[]': length, pop, push, concat, and 28 more.

    7     const wrapper = shallowMount(HelloWorld, {
                                       ~~~~~~~~~~

      node_modules/@vue/test-utils/dist/mount.d.ts:36:25
        36 export declare function mount<PropsOptions extends Readonly<ComponentPropsOptions>, RawBindings, D, C extends ComputedOptions = {}, M extends Record<string, Function> = {}, E extends EmitsOptions = Record<string, any>, Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, Extends extends ComponentOptionsMixin = ComponentOptionsMixin, EE extends string = string>(componentOptions: ComponentOptionsWithObjectProps<PropsOptions, RawBindings, D, C, M, E, Mixin, Extends, EE>, options?: MountingOptions<ExtractPropTypes<PropsOptions>, D>): VueWrapper<ComponentPublicInstance<ExtractPropTypes<PropsOptions>, RawBindings, D, C, M, E, VNodeProps & ExtractPropTypes<PropsOptions>>>;
                                   ~~~~~
        The last overload is declared here.

I'm not exactly sure why your change has caused this error -- I think it's because of the removal of Props. Is it possible that your change has unintentionally broken expected behaviour -- or is v3.0.0 code not compatible with examples from the RC guides?

https://github.com/vuejs/vue-next/pull/2145/files#diff-6633d3f630e1d004a742d4d2d2a3186dL178-L197

Thank you :)

@antfu antfu deleted the types/bug-component-instance-without-props branch September 20, 2020 05:33
@antfu
Copy link
Member Author

antfu commented Sep 20, 2020

@shrink Your problem does not seem to be introduced in this PR. I was working on the overload without props, it should not affect the example you provided. How about filing an issue to vue-test-utils? It seems like the error is thrown by the overloads of shallowMount.

@pikax
Copy link
Member

pikax commented Sep 20, 2020

@shrink this PR shouldn't introduce that error.

Update your shim:

declare module '*.vue' {
  import { DefineComponent } from 'vue';
  const component: DefineComponent;
  export default component;
}

For further questions you can ask on #typescript - Vue Discord

@shrink
Copy link

shrink commented Sep 20, 2020

@pikax Thank you very much -- that was the issue! I'll check out Discord if I encounter any further issues.

@antfu Thank you for the prompt response, apologies for incorrectly identifying this PR as the source of the issue :)

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.

None yet

4 participants