when providing initialData directly on a query, the type of data is guaranteed to be TData, not TData | undefined:
const { data } = useQuery(['test'], () => Promise.resolve('test'), { initialData: 'something' })
// 🚨 Object is possibly 'undefined'.(2532)
data.toUpperCase()
TypeScript playground
ideally, we could narrow the type when initialData is provided. This only works for initialData because initialData is executed in the constructor of the query, and because it is synchronous. Also, it can only work on v4 because in v3, undefined is technically still valid for the TData generic, so we cannot remove it from the union. In v4, undefined is illegal for successful queries, so that would now work.
Keep in mind that initialData can also be a function that returns TData | undefined, so this should also narrow if the function returns TData.
It does NOT work for:
placeholderData, because that will revert back to undefined when a query errors
initialData being provided globally, because TS cannot know that on an instance level. It needs to be explicitly passed to useQuery.
suspense or any other case because a query can be cancelled while it is initially fetching, in which case it will be reset to its initial state. queryClient.resetQueries also does that. Also, without network connection in the default network mode, the query will be in fetchStatus: 'paused' and will also not have data.
I guess we could potentially do this with another overload that has initialData provided and removes undefined from the result union, but we would also have do this for useQueries.
I would like to avoid having to add another generic to useQuery, as we already have four of them.
Because this is for v4, PRs should go to the beta branch please.
when providing
initialDatadirectly on aquery, the type ofdatais guaranteed to beTData, notTData | undefined:TypeScript playground
ideally, we could narrow the type when
initialDatais provided. This only works forinitialDatabecauseinitialDatais executed in the constructor of the query, and because it is synchronous. Also, it can only work onv4because inv3,undefinedis technically still valid for theTDatageneric, so we cannot remove it from the union. Inv4,undefinedis illegal for successful queries, so that would now work.Keep in mind that
initialDatacan also be a function that returnsTData | undefined, so this should also narrow if the function returnsTData.It does NOT work for:
placeholderData, because that will revert back toundefinedwhen a query errorsinitialDatabeing provided globally, because TS cannot know that on an instance level. It needs to be explicitly passed touseQuery.suspenseor any other case because a query can becancelledwhile it is initiallyfetching, in which case it will beresetto its initial state.queryClient.resetQueriesalso does that. Also, without network connection in the default network mode, the query will be infetchStatus: 'paused'and will also not have data.I guess we could potentially do this with another overload that has
initialDataprovided and removesundefinedfrom the result union, but we would also have do this foruseQueries.I would like to avoid having to add another generic to
useQuery, as we already have four of them.Because this is for v4, PRs should go to the
betabranch please.