Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # 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 :)

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants