Describe the bug
With @tanstack/react-query 5.104.0, an updater passed to setQueryData(queryOptions(...).queryKey, updater) fails when it narrows a discriminated union and spreads the narrowed value. The tagged key supplies the correct data type, but the inferred updater parameter is wrapped in NoInfer<Data>. The spread loses the variant-specific fields.
Explicitly annotating the updater parameter as Data | undefined makes the same update compile. This appears related to #11018, but affects the QueryClient cache updater rather than the useQuery result.
Minimal reproduction
import { QueryClient, queryOptions } from '@tanstack/react-query'
type Data =
| { kind: 'a'; value: number; requiredA: number }
| { kind: 'b'; value: number; requiredB: number }
const query = queryOptions({
queryKey: ['example'],
queryFn: async (): Promise<Data> => ({ kind: 'a', value: 1, requiredA: 1 }),
})
const client = new QueryClient()
// Correctly inferred from the tagged key.
const inferred: Data | undefined = client.getQueryData(query.queryKey)
// Fails with TS2345.
client.setQueryData(query.queryKey, (prev) => {
if (!prev || prev.kind !== 'a') return prev
return { ...prev, value: prev.value + 1 }
})
// The same update passes with an explicit parameter annotation.
client.setQueryData(query.queryKey, (prev: Data | undefined) => {
if (!prev || prev.kind !== 'a') return prev
return { ...prev, value: prev.value + 1 }
})
Steps to reproduce
Typecheck the example with TypeScript 5.8.3:
tsc --noEmit --strict --skipLibCheck --target es2023 --moduleResolution bundler --module esnext repro.ts
The unannotated updater fails with a return type containing { value: number; kind: "a" | "b" }, missing requiredA and requiredB. The annotated updater compiles.
Expected behavior
After prev.kind !== 'a' returns, spreading prev should preserve kind: 'a' and requiredA. The documented query-options key inference should allow this update without repeating the data type on the parameter.
Versions
@tanstack/react-query: 5.104.0
@tanstack/query-core: 5.104.0
- TypeScript: 5.8.3
- Platform: macOS; compile-time only
Additional context
The reproducer uses no application-specific wrappers, key registration, or casts. The reverse-inference guard should remain intact; this report is about preserving normal union narrowing and spread behavior while retaining that guard.
Describe the bug
With
@tanstack/react-query5.104.0, an updater passed tosetQueryData(queryOptions(...).queryKey, updater)fails when it narrows a discriminated union and spreads the narrowed value. The tagged key supplies the correct data type, but the inferred updater parameter is wrapped inNoInfer<Data>. The spread loses the variant-specific fields.Explicitly annotating the updater parameter as
Data | undefinedmakes the same update compile. This appears related to #11018, but affects the QueryClient cache updater rather than theuseQueryresult.Minimal reproduction
Steps to reproduce
Typecheck the example with TypeScript 5.8.3:
The unannotated updater fails with a return type containing
{ value: number; kind: "a" | "b" }, missingrequiredAandrequiredB. The annotated updater compiles.Expected behavior
After
prev.kind !== 'a'returns, spreadingprevshould preservekind: 'a'andrequiredA. The documented query-options key inference should allow this update without repeating the data type on the parameter.Versions
@tanstack/react-query: 5.104.0@tanstack/query-core: 5.104.0Additional context
The reproducer uses no application-specific wrappers, key registration, or casts. The reverse-inference guard should remain intact; this report is about preserving normal union narrowing and spread behavior while retaining that guard.