Returning defineComponent() inference not 'portable' without explicit return type annotation
Link to minimal reproduction
Steps to reproduce
Use VS Code with Volar (in Take Over mode)
Create a
.tsx
file which doesexport default
a generic function which returns a Vue Component usingdefineComponent()
Use the generic inside
props: {}
of the defined componentTo prevent this error, you need to explicitly specify the return type of the generic function with the
DefineComponent
and therefore explicitly defining the props type aswell. (e.g.DefineComponent<{myProp: text}>
)
What is expected?
Before vue@3.2.34
, there was no TypeScript compiler error shown.
What is actually happening?
A TypeScript error is shown:
The inferred type of 'StackedListGeneric' cannot be named without a reference to '.pnpm/@vue+shared@3.2.34/node_modules/@vue/shared'. This is likely not portable. A type annotation is necessary.ts(2742)
System Info
Package Manager: `pnpm` `v7`
Vue: `v3.2.34`
Any additional comments?
The TypeScript compiler error is not shown in Stackblitz. Open it in VS Code to see the compiler warning.
Edit 1: use plain .tsx file instead of violating SFC spec. Edit 2: update link to repro
Why are you doing that in an SFC and not a plain .tsx file?
That's not exactly the usage that's intended and tested against. as it's a violation of the SFC spec.
Why are you doing that in an SFC and not a plain .tsx file?
That's not exactly the usage that's intended and tested against. as it's a violation of the SFC spec.
Thanks for pointing this out!
Just out of habit... Didn't realise it is discouraged 😮.
I moved the function into a plain .tsx file, but the TypeScript error is still shown.
I updated the reproduction to use .tsx and included a demo use case.
The error is in GenericList.tsx
:
I tested against older versions of vue
. The version that introduced this issue seems to be vue@3.2.34
.
Thank you by the way @pikax, for your awesome presentation about Vue types! I'm really interested in Generic Vue components, and your talk helped me to understand the types better. 🙂
Simple workaround (may not work for all scenes): Add @vue/shared
as dep & add this to your project.
// type-fix.d.ts
import type {} from '@vue/shared'
After some time of exploration, I found the problem is a bit complex. It's caused by a series of combinations of different packages (vue, vue-tsc) & tools (typescript, pnpm). If the previous solution works, that's great and would be a neat workaround for the moment.
However if your project is large, that solution may still have some problems. My recommendation is locking all version of vue & related packages to 3.2.33
(including nested deps).
Seems @vue/test-utils
and class
& style
prop for component in tsx is broken with vue@3.2.34
. See
I believe this was caused by https://github.com/vuejs/core/commit/98b821d94a0a0fb4d7701809da6bec331a47e6e5 which altered the argument order of DefineComponent
.
Should be fixed by 8071ef47 which reverts the change. (Update: out in 3.2.35)