vuejs / language-tools

⚡ High-performance Vue language tooling based-on Volar.js
https://marketplace.visualstudio.com/items?itemName=Vue.volar
MIT License
5.84k stars 396 forks source link

Type checking fails for components loaded via `defineAsyncComponent` #4789

Open BlushingTomato opened 2 months ago

BlushingTomato commented 2 months ago

Vue - Official extension or vue-tsc version

2.1.4

VSCode version

1.92.2

Vue version

2.7.16

TypeScript version

5.5.4

System Info

No response

package.json dependencies

No response

Steps to reproduce

What is expected?

The check passing succesfully.

What is actually happening?

The following TS error:

TS2345: Argument of type '{}' is not assignable to parameter of type '(component: Component<DefaultData<never>, DefaultMethods<never>, DefaultComputed, DefaultProps, {}>) => void'.
  Type '{}' provides no match for the signature '(component: Component<DefaultData<never>, DefaultMethods<never>, DefaultComputed, DefaultProps, {}>): void'.

Link to minimal reproduction

No response

Any additional comments?

This issue started happening in 2.1.4, 2.1.2 seems to work fine.

KazariEX commented 2 months ago

I cannot reproduce it. Could you provide a minimal reproduction?

BlushingTomato commented 2 months ago

I tried creating a minimal reproduction, but cannot seem to reproduce it outside of our main repo 😞

I noticed that it also only happens for some components, not all of them. I'll keep looking as to what could be causing this.

BlushingTomato commented 2 months ago

Actually managed to reproduce it, you can see it here:

Seems to happen on defineAsyncComponent instances which do not have any props passed.

KazariEX commented 2 months ago

Enter the node_modules/.vue-global-types/vue_2.7_false.d.ts file, add the following content before line 102:

    : T extends () => any ? (props: {}, ctx?: any) => ReturnType<T>
+   : T extends (...args: any) => Promise<infer R> | void ? () => R
    : T extends (...args: any) => any ? T

Could this solve your problem?

BlushingTomato commented 2 months ago

The vue_2.7_false.d.ts file gets reset when I run the vue-tsc --noEmit command, so it keeps happening. Can I use a flag to disable that behavior?

KazariEX commented 2 months ago

You can patch the @vue/language-core/lib/codegen/globalTypes.js file as a temporary solution.

BlushingTomato commented 2 months ago

No, the issue sadly persists even after patching the file.

KazariEX commented 2 months ago

It solved your repro on my machine, so I don't how to confirm the issue that occurred on your main repository :(

BlushingTomato commented 2 months ago

I tested it on the repro on my machine too, where it failed 🤔

I've added : T extends (...args: any) => Promise<infer R> | void ? () => R after line 124 inside codegen/globalTypes, should I add it somewhere else?

BlushingTomato commented 2 months ago

Oh my god, I cannot read. I've added it before that line and now it works. I apologize for the inconvenience and thank you for the solution.

HryhoriiUstymenko commented 1 month ago

Hello, I stumbled upon the same issue. Looking forward to it being fixed!

KazariEX commented 1 month ago

The current solution is not elegant and may trigger other unexpected type inferences. We are currently unable to merge it into the main branch - please use the above workaround temporarily until then.