Subscribe on changes!

defineCustomElement type error when component defines emit and imports other component

avatar
Feb 23rd 2023

Vue version

3.2.47

Link to minimal reproduction

https://stackblitz.com/edit/vitejs-vite-jbymki?file=src/index.ts

Steps to reproduce

  1. Set up a new vue project using typescript and vite
  2. Create two minimal SFC components with lang="typescript"
  3. In one component import the other and define any emit using defineEmits and type declaration
  4. Create an index.ts and call defineCustomElement with the component from the step before
  5. execute vue-tsc

What is expected?

No error

What is actually happening?

src/index.ts:4:35 - error TS2769: No overload matches this call.
  The last overload gave the following error.
    Argument of type 'DefineComponent<{}, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, { click: () => void; }, string, PublicProps, Readonly<...> & { ...; }, {}>' is not assignable to parameter of type 'new (...args: any[]) => ComponentPublicInstance<{}, {}, {}, {}, {}, {}, {}, {}, false, ComponentOptionsBase<any, any, any, any, any, any, any, any, any, {}, {}, string>, {}>'.
      Type '{ $: ComponentInternalInstance; $data: {}; $props: Partial<{}> & Omit<Readonly<ExtractPropTypes<{}>> & { onClick?: (() => any) | undefined; } & VNodeProps & AllowedComponentProps & ComponentCustomProps, never>; ... 10 more ...; $watch<T extends string | ((...args: any) => any)>(source: T, cb: T extends (...args: any...' is not assignable to type 'ComponentPublicInstance<{}, {}, {}, {}, {}, {}, {}, {}, false, ComponentOptionsBase<any, any, any, any, any, any, any, any, any, {}, {}, string>, {}>'.
        Type '{ $: ComponentInternalInstance; $data: {}; $props: Partial<{}> & Omit<Readonly<ExtractPropTypes<{}>> & { onClick?: (() => any) | undefined; } & VNodeProps & AllowedComponentProps & ComponentCustomProps, never>; ... 10 more ...; $watch<T extends string | ((...args: any) => any)>(source: T, cb: T extends (...args: any...' is not assignable to type '{ $: ComponentInternalInstance; $data: {}; $props: {}; $attrs: Data; $refs: Data; $slots: Readonly<InternalSlots>; $root: ComponentPublicInstance<...> | null; ... 6 more ...; $watch<T extends string | ((...args: any) => any)>(source: T, cb: T extends (...args: any) => infer R ? (args_0: R, args_1: R) => any : (...ar...'.
          Types of property '$emit' are incompatible.
            Type '(event: "click") => void' is not assignable to type '(event: string, ...args: any[]) => void'.
              Types of parameters 'event' and 'event' are incompatible.
                Type 'string' is not assignable to type '"click"'.

4 const Comp1 = defineCustomElement(Comp1Vue);
                                    ~~~~~~~~

  node_modules/@vue/runtime-dom/dist/runtime-dom.d.ts:54:25
    54 export declare function defineCustomElement(options: {
                               ~~~~~~~~~~~~~~~~~~~
    The last overload is declared here.


Found 1 error in src/index.ts:4

System Info

No response

Any additional comments?

This might be an issue related to vue-tsc. But judging by the referenced files in the error message, I assume that this type-error resides in the vue codebase.

Context: We want to create a component library that provides Vue and web components.

avatar
Feb 23rd 2023

I think the issue is that Comp2 doesn't use TS, so it is interpreted as a JS file for TSC.

You have two options here:

  1. Set "allowJs": true in tsconfig.json's compilerOptions
  2. or add an empty script block to set the language to "ts".
<template><div></div></template>
<script setup lang="ts"></script>
avatar
Feb 23rd 2023

I think the issue is that Comp2 doesn't use TS, so it is interpreted as a JS file for TSC.

You have two options here:

1. Set `"allowJs": true` in `tsconfig.json`'s compilerOptions

2. or add an empty script block to set the language to "ts".
<template><div></div></template>
<script setup lang="ts"></script>

@LinusBorg Unfortunately not... I updated the stackblitz.

avatar
Feb 23rd 2023

I downloaded the repo, and it works fine locally with either of those changes. Though I needed to bust the cache by adding a blank line and saving Comp1.vue or something similar.

Edit: Seems to be a problem with vue-tsc. Works fine in the IDE with the changes I propsed, but vue-tsc still fails. That level of instability means its in Volar, I'd say.

Red squiggles:

Bildschirm­foto 2023-02-23 um 19 31 43

No red squiggles:

Bildschirm­foto 2023-02-23 um 19 31 31

... but still failing vue-tsc:

Bildschirm­foto 2023-02-23 um 19 34 57
avatar
Feb 24th 2023

Thanks for clarifiying! I created a new issue at https://github.com/vuejs/language-tools/issues/2450

avatar
Mar 21st 2023

This is defineCustomElement problem, here is minimal reproduction.

https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAbzgEwKYDNgDtUGECuAzjBCAKIA2qIqWMANChtnqZDnXAL5zpSlwA5ADd8qQQG4AUFIDGELMTi42ARgBqYuAF4mmHCvALaMABQIpcONWAxCALkSWrcWRWCyA1o9MBKHQB8cDBQYvTOXFJcvtJSaPp4RCTkVDR0poZgGmIxUkA

Instability is another TypeScript issue that can be reproduced in tsc with the following .ts content.

  • index.ts
import { defineCustomElement } from 'vue';
import Comp1Vue from './Comp1.vue';

defineCustomElement(Comp1Vue);
  • Comp1.vue.ts
import Comp2 from './Comp2.vue'; // remove this line, tsc error goes away

export default (await import('vue')).defineComponent({
  emits: ({} as {
    click(): void;
  })
})
  • Comp2.vue.ts
export default (await import('vue')).defineComponent({});
avatar
May 22nd 2023

Facing the same issue. When can the fix be review and merged?

avatar
Oct 27th 2023

Hello, my team is facing the same issue and it's blocking our use of vue-tcs. A pull request is also ready #7937 , are there any chances this will be fixed soon? If I can be helpful somehow, let me know :)
Thank you!