[vue-query]: Fresh Vue3 project + Tanstack - Typescript errors, This is likely not a portable.
Describe the bug
With a fresh Vue3 installation with @tanstack/vue-query installed - VSCode produces typescript errors, as seen in the screenshot.
It's not clear to me if this is an issue with tanstack-query, vue3 - or typescript. There seems to be various issues around that suggest it might be any of them.
Its worth noting that the project still runs and produces expected results.
tanstack/vue-query does not have this issue on V4. It only occurs after moving to V5.
Your minimal, reproducible example
https://github.com/cadriel/tanstack-query-issue
Steps to reproduce
- Clone the example project. https://github.com/cadriel/tanstack-query-issue
- Open the project in VSCode - ensure you've installed and configured the Vue dev tools (Volar, etc..)
- See the error as per the screenshot above.
Expected behavior
I'd expect to not see any errors in VSCode, and for the types to be correctly inferred.
How often does this bug happen?
Every time
Screenshots or Videos
Platform
macOS, VSCode.
Tanstack Query adapter
vue-query
TanStack Query version
V5+
TypeScript version
V5.2.2 (as per npm create vue@latest)
Additional context
No response
Some google results suggest not using pnpm - the provided example specifically rules this out by not using pnpm.
This has something to do with module resolution.
Adding "moduleResolution": "node", to tsconfig.app.json fixes the issue.
Also just importing type UseQueryReturnType without using it fixes the issue as well.
But that is a workaround. I will try to figure out why this happens.
Yes, you can add the type manually for the example. However, as soon as you add any complexity (mutations, etc..) - then it becomes very cumbersome to figure out what types to import.
I couldn't figure out what types to import at all for some circumstances.
The moduleResolution suggestion may cause other issues.
Ideally there should be no other requirements. Thanks for looking into this further.
I would consider this a showstopper, this seems like an extremely big issue in actually using vue-query
Seems to be an issue with multiple packages, the same problem occurs with @tanstack/react-query since V5 when "declaration": true is set:
We use query in our core-lib, switching to "moduleResolution": "node" fixes the error in the editor, but produces wrong .d.ts files later on.
With V4 the correct types looked like:
export declare const useTest: import("@tanstack/react-query").UseMutationResult<string, Error, void, unknown>;
With V5 the types are now:
export declare const useTest: import("@tanstack/react-query/build/legacy/types").UseMutationResult<string, Error, void, unknown>; which leads to errors in the consuming project.
The declaration: true comment above may provide a hint. There were a lot of upstream dependencies that required updates in order to support Typescript changes. There was a bit of turmoil for a month or two. It might also be related to Vite and browser module resolution that bought about those updates.
In any case, vue-query@v5 is in an unusable state for us because of this.
@DamianOsipiuk You may want to consider increasing priority if this affects multiple packages.
Just to give some update on this.
I did not figure out any good fix for this.
The most relevant comment i could find on this is https://github.com/microsoft/TypeScript/issues/47663#issuecomment-1519138189
What this means is if that you are re-exporting vue-query in your lib composables leveraging type inference, you need to at least re-export types from vue-query as it's transitive dependency of your package.
This should fix most of the issues, but i would appreciate input from any TS wizard if there is a better way to solve this.
@Andarist @mattpocock - TS wizards assemble... 🙈
I’ll take a look in an hour or so. I know what can usually be done when it comes to this error
I've done a quick analysis locally and i strongly believe that it's caused by tsup mangling~ (and renaming) exports in the declaration files. Instead of exporting UseQueryReturnType directly from useQuery-d58edace.d.ts and exporting it under the same name in index.d.ts, it exports it like this UseQueryReturnType as b and reexports it from index.d.ts like this: export { b as UseQueryReturnType } from './useQuery-d58edace.js';.
I think this might introduce an indirection that confuses TypeScript and it fails to recognize that this type is actually exported from @tanstack/vue-query. I patched declaration files locally to export UseQueryReturnType "directly" and the problem disappeared.
My recommendation would be to:
- report this to
tsup. I don't think this exports aliasing serves any real purpose in declaration files so I don't think it's worth doing - report this to TypeScript. I think that this is quite a basic aliasing case and that this could work better in TypeScript. A fix similar-ish to my https://github.com/microsoft/TypeScript/pull/56100 could fix this.
@Andarist I'll add that this is not exclusive to vue-query, I believe this has to do with declaration inside the /build/modern/types as i've got an issue authoring a library that uses tanstack react-query and I've got the same issue, so this must be stemming from the query-core
I tried re-creating it, the dependencies work fine in a simple repo, issue happens in monorepos specifically.
Turning off declaration in tsconfig fixes the issue, but obviously as i'm authoring a library this is not a sufficient solution for me. So this does seem to be an issue with transitive dependency linking.
Running tsc --noEmit --traceResolutions yields following errors:
======== Module name '@typescript/lib-scripthost' was not resolved. ========
File '/Users/samuel/Coding/qman/query/node_modules/.pnpm/[email protected]/node_modules/typescript/lib/package.json' does not exist according to earlier cached lookups.
File '/Users/samuel/Coding/qman/query/node_modules/.pnpm/[email protected]/node_modules/typescript/package.json' exists according to earlier cached lookups.
node_modules/.pnpm/@[email protected]/node_modules/@tanstack/query-core/build/modern/hydration.d.cts:1:210 - error TS1479: The current file is a CommonJS module whose imports will produce 'require' calls; however, the referenced file is an ECMAScript module and cannot be imported with 'require'. Consider writing a dynamic 'import("./queryClient-iw7Hbrkm.js")' call instead.
1 import { o as Mutation, n as Query, H as QueryOptions, ap as MutationOptions, b as QueryClient, al as MutationKey, p as MutationState, an as MutationMeta, q as QueryKey, l as QueryState, B as QueryMeta } from './queryClient-iw7Hbrkm.js';
~~~~~~~~~~~~~~~~~~~~~~~~~~~
node_modules/.pnpm/@[email protected]/node_modules/@tanstack/query-core/build/modern/index.d.cts:1:2466 - error TS1479: The current file is a CommonJS module whose imports will produce 'require' calls; however, the referenced file is an ECMAScript module and cannot be imported with 'require'. Consider writing a dynamic 'import("./queryClient-iw7Hbrkm.js")' call instead.
1 export { aB as CancelOptions, C as CancelledError, t as DataTag, D as DefaultError, aA as DefaultOptions, V as DefaultedInfiniteQueryObserverOptions, O as DefaultedQueryObserverOptions, aj as DefinedInfiniteQueryObserverResult, ac as DefinedQueryObserverResult, Y as FetchInfiniteQueryOptions, a3 as FetchNextPageOptions, a4 as FetchPreviousPageOptions, X as FetchQueryOptions, a6 as FetchStatus, z as GetNextPageParamFunction, G as GetPreviousPageParamFunction, A as InfiniteData, ae as InfiniteQueryObserverBaseResult, ag as InfiniteQueryObserverLoadingErrorResult, af as InfiniteQueryObserverLoadingResult, S as InfiniteQueryObserverOptions, ah as InfiniteQueryObserverRefetchErrorResult, ak as InfiniteQueryObserverResult, ai as InfiniteQueryObserverSuccessResult, K as InfiniteQueryPageParamsOptions, I as InitialDataFunction, J as InitialPageParam, a1 as InvalidateOptions, $ as InvalidateQueryFilters, as as MutateFunction, ar as MutateOptions, o as Mutation, M as MutationCache, d as MutationCacheNotifyEvent, f as MutationFilters, ao as MutationFunction, al as MutationKey, an as MutationMeta, e as MutationObserver, at as MutationObserverBaseResult, aw as MutationObserverErrorResult, au as MutationObserverIdleResult, av as MutationObserverLoadingResult, aq as MutationObserverOptions, ay as MutationObserverResult, ax as MutationObserverSuccessResult, ap as MutationOptions, p as MutationState, am as MutationStatus, E as NetworkMode, N as NoInfer, aE as NotifyEvent, aD as NotifyEventType, F as NotifyOnChangeProps, P as PlaceholderDataFunction, x as QueriesPlaceholderDataFunction, n as Query, Q as QueryCache, a as QueryCacheNotifyEvent, b as QueryClient, az as QueryClientConfig, g as QueryFilters, u as QueryFunction, w as QueryFunctionContext, q as QueryKey, y as QueryKeyHashFunction, B as QueryMeta, c as QueryObserver, a7 as QueryObserverBaseResult, a9 as QueryObserverLoadingErrorResult, a8 as QueryObserverLoadingResult, L as QueryObserverOptions, aa as QueryObserverRefetchErrorResult, ad as QueryObserverResult, ab as QueryObserverSuccessResult, H as QueryOptions, v as QueryPersister, l as QueryState, a5 as QueryStatus, _ as RefetchOptions, a0 as RefetchQueryFilters, R as Register, a2 as ResetOptions, Z as ResultOptions, aC as SetDataOptions, T as ThrowOnError, U as Updater, W as WithRequired, s as dataTagSymbol, h as hashKey, j as isCancelledError, i as isServer, k as keepPreviousData, m as matchQuery, r as replaceEqualDeep } from './queryClient-iw7Hbrkm.js';
~~~~~~~~~~~~~~~~~~~~~~~~~~~
node_modules/.pnpm/@[email protected]/node_modules/@tanstack/query-core/build/modern/infiniteQueryObserver.d.cts:1:342 - error TS1479: The current file is a CommonJS module whose imports will produce 'require' calls; however, the referenced file is an ECMAScript module and cannot be imported with 'require'. Consider writing a dynamic 'import("./queryClient-iw7Hbrkm.js")' call instead.
1 import { D as DefaultError, A as InfiniteData, q as QueryKey, c as QueryObserver, ak as InfiniteQueryObserverResult, aG as ObserverFetchOptions, b as QueryClient, S as InfiniteQueryObserverOptions, aH as NotifyOptions, V as DefaultedInfiniteQueryObserverOptions, a3 as FetchNextPageOptions, a4 as FetchPreviousPageOptions, n as Query } from './queryClient-iw7Hbrkm.js';
~~~~~~~~~~~~~~~~~~~~~~~~~~~
node_modules/.pnpm/@[email protected]/node_modules/@tanstack/query-core/build/modern/queriesObserver.d.cts:1:156 - error TS1479: The current file is a CommonJS module whose imports will produce 'require' calls; however, the referenced file is an ECMAScript module and cannot be imported with 'require'. Consider writing a dynamic 'import("./queryClient-iw7Hbrkm.js")' call instead.
1 import { ad as QueryObserverResult, b as QueryClient, L as QueryObserverOptions, aH as NotifyOptions, n as Query, q as QueryKey, c as QueryObserver } from './queryClient-iw7Hbrkm.js';
~~~~~~~~~~~~~~~~~~~~~~~~~~~
node_modules/.pnpm/@[email protected][email protected]/node_modules/@tanstack/react-query/build/modern/HydrationBoundary.d.cts:1:24 - error TS7016: Could not find a declaration file for module 'react'. '/Users/samuel/Coding/qman/query/node_modules/.pnpm/[email protected]/node_modules/react/index.js' implicitly has an 'any' type.
Try `npm i --save-dev @types/react` if it exists or add a new declaration (.d.ts) file containing `declare module 'react';`
1 import * as React from 'react';
~~~~~~~
node_modules/.pnpm/@[email protected][email protected]/node_modules/@tanstack/react-query/build/modern/isRestoring.d.cts:1:24 - error TS7016: Could not find a declaration file for module 'react'. '/Users/samuel/Coding/qman/query/node_modules/.pnpm/[email protected]/node_modules/react/index.js' implicitly has an 'any' type.
Try `npm i --save-dev @types/react` if it exists or add a new declaration (.d.ts) file containing `declare module 'react';`
1 import * as React from 'react';
~~~~~~~
node_modules/.pnpm/@[email protected][email protected]/node_modules/@tanstack/react-query/build/modern/QueryClientProvider.d.cts:1:24 - error TS7016: Could not find a declaration file for module 'react'. '/Users/samuel/Coding/qman/query/node_modules/.pnpm/[email protected]/node_modules/react/index.js' implicitly has an 'any' type.
Try `npm i --save-dev @types/react` if it exists or add a new declaration (.d.ts) file containing `declare module 'react';`
1 import * as React from 'react';
~~~~~~~
node_modules/.pnpm/@[email protected][email protected]/node_modules/@tanstack/react-query/build/modern/QueryClientProvider.d.cts:10:89 - error TS2503: Cannot find namespace 'JSX'.
10 declare const QueryClientProvider: ({ client, children, }: QueryClientProviderProps) => JSX.Element;
~~~
node_modules/.pnpm/@[email protected][email protected]/node_modules/@tanstack/react-query/build/modern/QueryErrorResetBoundary.d.cts:1:24 - error TS7016: Could not find a declaration file for module 'react'. '/Users/samuel/Coding/qman/query/node_modules/.pnpm/[email protected]/node_modules/react/index.js' implicitly has an 'any' type.
Try `npm i --save-dev @types/react` if it exists or add a new declaration (.d.ts) file containing `declare module 'react';`
1 import * as React from 'react';
~~~~~~~
Found 9 errors in 8 files.
Errors Files
1 node_modules/.pnpm/@[email protected]/node_modules/@tanstack/query-core/build/modern/hydration.d.cts:1
1 node_modules/.pnpm/@[email protected]/node_modules/@tanstack/query-core/build/modern/index.d.cts:1
1 node_modules/.pnpm/@[email protected]/node_modules/@tanstack/query-core/build/modern/infiniteQueryObserver.d.cts:1
1 node_modules/.pnpm/@[email protected]/node_modules/@tanstack/query-core/build/modern/queriesObserver.d.cts:1
1 node_modules/.pnpm/@[email protected][email protected]/node_modules/@tanstack/react-query/build/modern/HydrationBoundary.d.cts:1
1 node_modules/.pnpm/@[email protected][email protected]/node_modules/@tanstack/react-query/build/modern/isRestoring.d.cts:1
2 node_modules/.pnpm/@[email protected][email protected]/node_modules/@tanstack/react-query/build/modern/QueryClientProvider.d.cts:1
1 node_modules/.pnpm/@[email protected][email protected]/node_modules/@tanstack/react-query/build/modern/QueryErrorResetBoundary.d.cts:1
You can find the entire paste here https://pastebin.com/NfJX8gsX
This would probably confirm what you referneced in your comment above, that this for some reason makes typescript detect the type export from the generated build js files, instead of the type declarations on .d.ts. This is causing resolution issues with the require syntax.
I also know this was not an issue in older monorepo projects using tanstack query, since I had one working fine, so must be caused by some of the type changes on your end.
If you need / want any more info let me know, i sadly didn't have time to do any patching / tinkering as this is a hobby project and I'm quite busy with work at the moment.
that this for some reason makes typescript detect the type export from the generated build js files, instead of the type declarations on .d.ts.
I'd need a pointer as to where that happens - the log is, well, quite long and I lack a lot of context here. I just have investigated one concrete case here.
This is causing resolution issues with the require syntax.
This might potentially be a different issue - but hard to tell without seeing a repro case.
I also know this was not an issue in older monorepo projects using tanstack query, since I had one working fine, so must be caused by some of the type changes on your end.
Maybe the new release includes package.json#exports and your monorepo is using moduleResolution: nodenext (or similar)?
You can always fix those issues by using explicit type annotations. I have a plan to investigate this more on the TS side of things during the Christmas break - but either way, a fix in the compiler won't be released until at least TS 5.4 (in like 3 months since now or smth like that).
So I'd encourage the maintainers of this repo to investigate alternative solutions in the meantime. The "best" one would be to fix this in tsup since that would benefit everybody using that project.
@Andarist I pushed the issue to git https://github.com/hulla-dev/qman/tree/feat/query
Specifically the issue occurs under /query/src/use.ts
I have both package.json#xports and moduleResolution: nodenext set up, but I haven't heard of this happening. Sorry to muddy the waters if this turns out to be something else. Feel free to take a look
EDIT: For people stuck with this issue: This most likely can be fixed by simply annotating a return type to your function, i.e.
function x() {
return useQuery(...)
}
just needs an annotation - which by the way can even be explicitly inferred:
function x(): ReturnType<typeof useQuery> {
return useQuery(...)
}
Obviously it's not ideal, but it's the cleanest workaround rather than messing up your tsconfig by turning off your declarations or enabling preserveSymlinks both of which have (likely, depending on your use-case) undesired side-effects
@Andarist I pushed the issue to git https://github.com/hulla-dev/qman/tree/feat/query
Specifically the issue occurs under
/query/src/use.tsI have both
package.json#xportsandmoduleResolution: nodenextset up, but I haven't heard of this happening. Sorry to muddy the waters if this turns out to be something else. Feel free to take a lookEDIT: For people stuck with this issue: This most likely can be fixed by simply annotating a return type to your function, i.e.
function x() { return useQuery(...) }just needs an annotation - which by the way can even be explicitly inferred:
function x(): ReturnType<typeof useQuery> { return useQuery(...) }Obviously it's not ideal, but it's the cleanest workaround rather than messing up your tsconfig by turning off your
declarations or enablingpreserveSymlinksboth of which have (likely, depending on your use-case) undesired side-effects
This isn't a solution. It was also already mentioned in this thread; https://github.com/TanStack/query/issues/6318#issuecomment-1797018783
Yes, explicitly adding the annotation for a simple useQuery works - but it becomes infinitely more complex for mutations or any other more complex functions - making it not viable.
I started to investigate this in TypeScript and rechecked the original repro. It turns out that removing the renames doesn't fix this - but a direct export of the type does. What I mean is that if this file would just type UseQueryReturnType<... and if this file would just export { UseQueryReturnType } from './useQuery-CPqkvEsh.js'; then it would work.
Merry Christmas: https://github.com/microsoft/TypeScript/pull/56857
@Andarist you're a wizard my man, great job and enjoy your holidays 🎄
@hulla-dev the TS1479: The current file is a CommonJS module whose imports will produce 'require' calls; however, the referenced file is an ECMAScript module and cannot be imported with 'require'. issue should be fixed as of #6585. Please let me know if it still appears in a separate issue - I think it's unrelated to this.
@DamianOsipiuk @Andarist thanks for the debugging on this so far. With tsup v8, it's introduced an experimentalDts option which uses @microsoft/api-extractor. I'm wondering if we might have better luck using this?
From what I can see, it merges most declaration into a _tsup-dts-rollup.d.ts file, then re-exports the relevant types from each declaration.
For example useQuery.d.ts looks like this:
export { useQuery_alias_1 as useQuery } from './_tsup-dts-rollup';
export { UseQueryOptions_alias_1 as UseQueryOptions } from './_tsup-dts-rollup';
export { UndefinedInitialQueryOptions } from './_tsup-dts-rollup';
export { DefinedInitialQueryOptions } from './_tsup-dts-rollup';
export { UseQueryReturnType_alias_1 as UseQueryReturnType } from './_tsup-dts-rollup';
export { UseQueryDefinedReturnType_alias_1 as UseQueryDefinedReturnType } from './_tsup-dts-rollup';
It does look like it's missing .js extensions, which I think are necessary. Also, as the name suggests, it's also experimental, but it is intended to fix issues with the original deprecated rollup-plugin-dts plugin.
It works with latest v4 TypeScript and with "moduleResolution": "node". TypeScript V5 didnt work even when I tried suggested workarounds. But, in template, data is of type any, even if in script tag data shows the right Ref with type
My PR has been merged so you should be able to start using [email protected] tomorrow if this is a big problem for you and if you are willing to use the nightly TS version.
@lachlancollins this experimentalDts looks like a promising workaround - since flat-bundling declarations should avoid this TS problem.
@Andarist's fix does not seem to work for me. I have moduleResolution set to bundler. (this is in a react project but I think the issues are related) 🤔
Please always try to share a repro case in a runnable form - either by providing a git repository to clone or a codesandbox. I can’t investigate what I can’t debug.
Sure, sorry. I will try and put it together. Thank you for all you do in the TypeScript community :)
@Andarist Thanks for your effort so far.
I've updated the original repro (https://github.com/cadriel/tanstack-query-issue) and upgraded to ts 5.4.0-dev however the issue remains.
Was there something else that needed to be adjusted?
I just tested it out and it works. I'm almost sure that you have forgotten to use the workspace TS version (you can choose "Select TypeScript Version..." from the command palette. This is such a big annoyance when using VS Code - you have to do it in each project separately 🙈
I just tested it out and it works. I'm almost sure that you have forgotten to use the workspace TS version (you can choose "Select TypeScript Version..." from the command palette. This is such a big annoyance when using VS Code - you have to do it in each project separately 🙈
You're 100% correct. I always forget this - but yeah, I selected the project version and the lint issues went away.
i don't get it. is using typescript 5.4.0-dev or the latest 5.4.0-beta would help resolve the issue ?
Using the beta should resolve the issue that I was able to diagnose and fix here. If the issue persist please share a repro case.
sorry for the noise, switching the project to 5.4.0-beta and VSCode with CMD + P Select TypeScript Version... to the project version "solved" the issue, too bad it's not working with previous 5.3.0 though.
Anyway, switching to the beta of TS isn't a good solution in case you have other dependencies that require lower version (like eslint-typescript).