Weird type bug when using `queryOptions` with `useQueries`
If you have a type where the only required key is
name
, the types of results
in the combine
function seems to be wrong. Any ideas on why this is?
6 Replies
optimistic-gold•3mo ago
combine
doesn't have anything to do with it, it still types wrong without it: https://www.typescriptlang.org/play/?#code/JYWwDg9gTgLgBAbzgRwK4FMoE8DyYbAQB2AzgDRyonoCKGUw6JcAvnAGZQQhwBEAAjACGpYQGMA1gHoo6IWJgBaNJiy8A3AFgAUDphYw6OACEuE9EQAqBowF5EOuHCJCQ6AFxwSMBkQDmWtosgTpixN5wAEZmFngE4XD2KthxhKQAFAiOKPRYANLoWJ4A2rzREOZEvAC6ZNnJWABiRJ7pAJSJAHzO6ADucAAKXCDA1AA8phUW1oad6e1diCxtdUFtIdr6hnAA6tASwP4zdg7aTkQQMAByrh5ePocBOsE6oeHwvfuPqQlJuT8ZLJnHKqApFOClT5QA7+GqrJwNZqtDq2bpEPqDYajdBjPbQx7HOYLVFLFbPdavbTsVBEBRpSjUPEwvx0TCMEgLIFOMKiCFIAAmQmEnkFwkmlWOrGqiQZtHo7My2QR8qYJXKlQBJGq2WWG2yPIiAqFQhFxqZBJsrBlVDlbKYiuByrtJBKUOZmtqSrgYRAkUOd3SshIqAANjASCjulynDHZDBUFAiKcYym4FIpHAg6GYAA6UVCOCjb3QWQKENYOBbdD8uBCZgAA3NR0tAB9KER+eh2P7+fWvSn854s2GSDmQEIwPNhzBI5mmNm88ayY7U+m58GwznRgMLPzHoXmGEoKWYOXKzYa3W4PXIhAICG5ER6xQLvAAFZUeD19hCEPUPsrimhgdo8Q7ziOOYkNw6BTuBM6LNOW4kDuIH+MuqasIEKYsPCrAUrowLZPm4rTDY2RrgAegA-NkRFml8zaGORGbUc8OhAA
I don't have a good answer besides a workaround by adding something like _bogus: never
to your type. I know in the past Dominik has said types in useQueries
are vastly more complicated than useQuery
and some have limitations (typescript simply can't handle some things, yet)TS Playground - An online editor for exploring TypeScript and JavaS...
The Playground lets you write TypeScript or JavaScript online in a safe and sharable way.
like-gold•3mo ago
I was interested in this, since it seemed like an absolutely hilarious issue, and so I went on a bit of a hunt.
In the types for
useQueries
, there is a utility type called QueriesResults which is used to get the return type of useQueries
, and this type (among several others in the file), reference a utility typeGetDefinedOrUndefinedQueryResult
which uses the type of initialData to determine if the query has default data or not.
The relevant start of this type is as follows:
Well, urns out that the type of our TInitialData
in our broken example that @troywoy linked is BrokenType | InitialDataFunction<BrokenType>
. This is because we are first checking if T extends initialData?
(which will match every time that initialData does or more importantly doesn't exist on the object)
Further investigation shows that InitialDataFunction
is defined as the below type in querycore:
Well the thing is, () => T | undefined
might look like a function, functions in javascript are actually objects, and by default, they have several properties on them, one of which is this: { name: string }
. You can verify this by simply attempting to access a key on a function type and will see that several exist (although don't show visibly when you hover example
normally):
So in conclusion, if your value is an object that is a subset of the base object that all functions in JavaScript extend, then the GetDefinedOrUndefinedQueryResult
utility type is going to fail to get pass this check, because () => any
does in fact extend { name: string }
, and such, your type is DefinedQueryOptions
.
I'll update this post once I've thought of a good solution to that, and will see if I can make a PR tonight or tomorrow. but in the meantime, that was the problem for anyone interestedlike-gold•3mo ago
If anyone is interested, I have made a fix here:
https://github.com/TanStack/query/pull/9278
GitHub
fix(react-query): update Incorrect Inference of GetDefinedOrUndefin...
Overview
This PR resolves an issue that was brought up in discord where using queryOptions where TQueryFnData was { name: string }, would cause the type of TData on useQueries to be { name: string ...
exotic-emerald•3mo ago
NO way 🤪
What a great find
optimistic-gold•3mo ago
Nice. What you say makes total sense and what a quirk
adverse-sapphireOP•3mo ago
Thanks for looking into this!