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
genetic-orange•6mo 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.
xenogeneic-maroon•6mo 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 interestedxenogeneic-maroon•6mo 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 ...
optimistic-gold•6mo ago
NO way 🤪
What a great find
genetic-orange•6mo ago
Nice. What you say makes total sense and what a quirk
unwilling-turquoiseOP•6mo ago
Thanks for looking into this!