Subscribe on changes!

defineProps cannot handle too complex definition

avatar
Aug 1st 2021

Version

3.1.5

Reproduction link

see Steps to reproduce

Steps to reproduce

<script setup lang="ts">
const props = defineProps<{
  foobar: {
    [key: string]: {
      bar: string
    }
  }
}>()
</script>

Run:

$ npx vue-tsc
$ npx vue-dts-gen Test.vue

What is expected?

Pass two command and get .d.ts file correctly.

What is actually happening?

Will output with error on vue-dts-gen:

lib/Test.vue.ts:4:3 - error TS2769: No overload matches this call.
  The last overload gave the following error.
    Type 'undefined' is not assignable to type 'Readonly<ComponentPropsOptions<Data>> & ThisType<void>'.
      Type '(this: void, __props: { foobar: { [key: string]: { bar: string; }; }; }, { expose }: SetupContext<EmitsOptions>) => { props: { foobar: { [key: string]: { bar: string; }; }; }; }' is not assignable to type '(this: void, props: Readonly<LooseRequired<Readonly<readonly unknown[] & { [x: number]: string; } & { [iterator]?: IterableIterator<string> | undefined; toString?: string | undefined; toLocaleString?: string | undefined; concat?: string[] | undefined; ... 19 more ...; flat?: unknown[] | undefined; }> | Readonly<...>...'.
        Types of parameters '__props' and 'props' are incompatible.
          Property 'foobar' is missing in type 'Readonly<LooseRequired<Readonly<readonly unknown[] & { [x: number]: string; } & { [iterator]?: IterableIterator<string> | undefined; toString?: string | undefined; toLocaleString?: string | undefined; concat?: string[] | undefined; ... 19 more ...; flat?: unknown[] | undefined; }> | Readonly<...>>>' but required in type '{ foobar: { [key: string]: { bar: string; }; }; }'.

4   props: {
    ~~~~~

  node_modules/@vue/runtime-core/dist/runtime-core.d.ts:422:5
    422     props: PropsOptions & ThisType<void>;
            ~~~~~
    The expected type comes from property 'props' which is declared here on type 'ComponentOptionsWithObjectProps<Readonly<ComponentPropsOptions<Data>>, { props: { foobar: { [key: string]: { bar: string; }; }; }; }, unknown, {}, {}, ComponentOptionsMixin, ... 4 more ..., { ...; } | {}>'
  node_modules/@vue/runtime-core/dist/runtime-core.d.ts:587:25
    587 export declare function defineComponent<PropsOptions extends Readonly<ComponentPropsOptions>, RawBindings, D, C extends ComputedOptions = {}, M extends MethodOptions = {}, Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, Extends extends ComponentOptionsMixin = ComponentOptionsMixin, E extends EmitsOptions = Record<string, any>, EE extends string = string>(options: ComponentOptionsWithObjectProps<PropsOptions, RawBindings, D, C, M, Mixin, Extends, E, EE>): DefineComponent<PropsOptions, RawBindings, D, C, M, Mixin, Extends, E, EE>;
                                ~~~~~~~~~~~~~~~
    The last overload is declared here.
lib/Test.vue.ts:7:3 - error TS2769: No overload matches this call.
  The last overload gave the following error.
    Type 'undefined' is not assignable to type 'Readonly<ComponentPropsOptions<Data>> & ThisType<void>'.
      Type '(this: void, __props: { foobar: { [key: string]: { bar: string; }; }; }, { expose }: SetupContext<EmitsOptions>) => { props: { foobar: { [key: string]: { bar: string; }; }; }; }' is not assignable to type '(this: void, props: Readonly<LooseRequired<Readonly<readonly unknown[] & { [x: number]: string; } & { [iterator]?: IterableIterator<string> | undefined; toString?: string | undefined; toLocaleString?: string | undefined; concat?: string[] | undefined; ... 19 more ...; flat?: unknown[] | undefined; }> | Readonly<...>...'.
        Types of parameters '__props' and 'props' are incompatible.
          Property 'foobar' is missing in type 'Readonly<LooseRequired<Readonly<readonly unknown[] & { [x: number]: string; } & { [iterator]?: IterableIterator<string> | undefined; toString?: string | undefined; toLocaleString?: string | undefined; concat?: string[] | undefined; ... 19 more ...; flat?: unknown[] | undefined; }> | Readonly<...>>>' but required in type '{ foobar: { [key: string]: { bar: string; }; }; }'.

7   setup(__props: {
    ~~~~~

  lib/Test.vue.ts:8:3
    8   foobar: {
        ~~~~~~
    'foobar' is declared here.
  node_modules/@vue/runtime-core/dist/runtime-core.d.ts:391:5
    391     setup?: (this: void, props: Readonly<LooseRequired<Props & UnionToIntersection<ExtractOptionProp<Mixin>> & UnionToIntersection<ExtractOptionProp<Extends>>>>, ctx: SetupContext<E>) => Promise<RawBindings> | RawBindings | RenderFunction | void;
            ~~~~~
    The expected type comes from property 'setup' which is declared here on type 'ComponentOptionsWithObjectProps<Readonly<ComponentPropsOptions<Data>>, { props: { foobar: { [key: string]: { bar: string; }; }; }; }, unknown, {}, {}, ComponentOptionsMixin, ... 4 more ..., { ...; } | {}>'
  node_modules/@vue/runtime-core/dist/runtime-core.d.ts:587:25
    587 export declare function defineComponent<PropsOptions extends Readonly<ComponentPropsOptions>, RawBindings, D, C extends ComputedOptions = {}, M extends MethodOptions = {}, Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, Extends extends ComponentOptionsMixin = ComponentOptionsMixin, E extends EmitsOptions = Record<string, any>, EE extends string = string>(options: ComponentOptionsWithObjectProps<PropsOptions, RawBindings, D, C, M, Mixin, Extends, E, EE>): DefineComponent<PropsOptions, RawBindings, D, C, M, Mixin, Extends, E, EE>;
                                ~~~~~~~~~~~~~~~
    The last overload is declared here.

The key part should be this line:

Property 'foobar' is missing in type 'Readonly<LooseRequired<Readonly<readonly unknown[] & { [x: number]: string; } & { [iterator]?: IterableIterator<string> | undefined; toString?: string | undefined; toLocaleString?: string | undefined; concat?: string[] | undefined; ... 19 more ...; flat?: unknown[] | undefined; }> | Readonly<...>>>'

In Vue's definition, props should be Readonly<LooseRequired<Readonly<readonly PropsType>>>, but the compiler mis-calculated the PropsType to unknown[] & { [x: number]: string; } & .... This caused type-check and definition exporting via TypeScript compiler failed.


I'm not sure if this is bug in Vue, vue-dts-gen or TypeScript. As I know, vue-dts-gen uses .ts file generated from Vue compiler directly, so maybe this issue is related to Vue or TS?

(Also happens on 3.2.0-beta.7)

avatar
Aug 1st 2021

Tested on a project and it doesn't fail. So it might be a problem with vue-dts-gen. Open an issue there or open a PR here with a failing test to fix (equivalent of reproduction)