setQueryData updater loses discriminated-union fields when spreading inferred NoInfer data
Los mantenedores suelen responder en 1 día
@boriskozak ya está trabajando en esto.
Desde el 4/10/2026.
Evaluación
- Dificultad
- 4/5
- Tiempo estimado
- 3-5 días
- Aptitud para principiantes
- 68/100
- Tipo de issue
- Error
- Claridad
- Bien especificado
- Estado de actividad
- Activo
- Stack tecnológico
- typescript
- Área
- api
Línea de trabajo
Start with the minimal reproduction and the QueryClient.setQueryData and queryOptions entry points, focusing on how the updater parameter uses NoInfer. Run the provided TypeScript command before and after changes. Done means the unannotated updater compiles, preserves the narrowed discriminated-union fields, and the reverse-inference guard remains intact.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
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.
- Lenguaje dominante
- TypeScript
- Estrellas
- 50.4k
- Forks
- 4.2k
- Merge medio
- 11 h 33 min
- PR fusionados (30 d)
- 421
Preparar el entorno
- Sin Dockerfile ni archivo de Docker Compose
- Tiene una plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de TanStack/query
-
solid-query: STRICT_READ_UNTRACKED on Solid 2 — client()/options() read in component body (useMutation, useBaseQuery)Quizá libre de nuevo Un pull request para esta issue se cerró sin fusionarse. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 84/100
TanStack/query#11358 · 2 comentarios · 1 reacción ·
Los mantenedores suelen responder en 1 día
-
solid-query: switching the queryClient accessor strands the new client's cache (subscription stays on the old observer)Posiblemente ocupada @MaNaN1803 la tomó hace 75 días. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 84/100
TanStack/query#11106 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
Dificultad 4/5 3-5 días Aptitud para principiantes 45/100
Los mantenedores suelen responder en 1 día
-
setQueryData: NoInfer loses discriminated-union members when spreading a narrowed updater valuePosiblemente ocupada @iosayin la tomó hace 1 día. Abierto
Dificultad 4/5 3-5 días Aptitud para principiantes 55/100
Los mantenedores suelen responder en 1 día
-
[vue-query]: UseMutationReturnType default names unexported MutationResult (TS2883) 🤖🤖🤖Posiblemente ocupada Un pull request vinculado a esta issue está abierto o ya se fusionó. Abierto
Dificultad 3/5 1-2 días Aptitud para principiantes 68/100
Los mantenedores suelen responder en 1 día
Todos los issues de TanStack/query
Issues similares
-
area:docs bug triage:confirmed
Dificultad 2/5 1-3 horas Aptitud para principiantes 74/100
Cotal-AI/Cotal#2875 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
GLM-5.3 available on bedrock nowAbierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 65/100
anomalyco/models.dev#8862 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
fix(data-lake): wizard source step still previews the local slug, not the server-disambiguated onePosiblemente ocupada Un pull request vinculado a esta issue está abierto o ya se fusionó. Abiertodata-lake
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
Los mantenedores suelen responder en 1 día
-
ready-for-triage
Dificultad 1/5 Menos de una hora Aptitud para principiantes 88/100
konflux-ci/konflux-ui#1596 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
enhancement good first issue priority: low size: XS
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
Los mantenedores suelen responder en 1 día