Skip to content

fix(query-core): use built-in NoInfer for generic indexed-access types#10593

Open
ousamabenyounes wants to merge 4 commits intoTanStack:mainfrom
ousamabenyounes:fix/issue-9937
Open

fix(query-core): use built-in NoInfer for generic indexed-access types#10593
ousamabenyounes wants to merge 4 commits intoTanStack:mainfrom
ousamabenyounes:fix/issue-9937

Conversation

@ousamabenyounes
Copy link
Copy Markdown
Contributor

@ousamabenyounes ousamabenyounes commented Apr 26, 2026

Summary

Fixes #9937.

Root cause

The public NoInfer<T> exported from @tanstack/query-core is defined as the historical pre-TS-5.4 trick:

export type NoInfer<T> = [T][T extends any ? 0 : never]

When T is a generic indexed-access type (e.g. DataTypeToEntity[DT] inside a function generic over DT extends keyof DataTypeToEntity), TypeScript fails to recognize that NoInfer<DataTypeToEntity[DT]> and DataTypeToEntity[DT] are the same:

Argument of type 'NoInfer<DataTypeToEntity[DT]>' is not assignable to parameter of type 'DataTypeToEntity[DT]'.
  Type '[DataTypeToEntity[DT]]' is not assignable to type 'DataTypeToEntity'.

The package already requires TypeScript ≥ 5.4 (lowest CI target is typescript@5.4), so the built-in intrinsic NoInfer is available everywhere it ships.

Fix

  • Add a tiny packages/query-core/src/noInfer.ts that re-exports the built-in NoInfer under an IntrinsicNoInfer<T> alias, sidestepping the self-shadowing problem when delegating from a same-named export.
  • Change export type NoInfer<T> in packages/query-core/src/types.ts to IntrinsicNoInfer<T>.
  • Update packages/vue-query/src/queryClient.ts: super.setQueryData<TData>(...) forwards the TData generic explicitly so the stricter built-in NoInfer<TData> return type stays satisfied (previously the unknown returned from the unparameterized call was passing only because the loose tuple-index trick masked it).

The public NoInfer export keeps the same identity, so no consumer-visible API change.

Verification

Added type test in packages/react-query/src/__tests__/useQuery.test-d.tsx (generic indexed access TData) that mirrors the issue's repro: useQuery inside a function generic over <TDataType extends DataType> whose data is then forwarded to getLabel(_, data: DataTypeToEntity[TDataType]). Without the fix it errors with the exact [DataTypeToEntity[DT]] is not assignable message; with the fix it type-checks.

Local check matrix (all green):

  • pnpm exec nx run @tanstack/query-core:test:lib
  • pnpm exec nx run @tanstack/query-core:test:types (TS 5.4–6.0)
  • pnpm exec nx run @tanstack/query-core:test:eslint
  • pnpm exec nx run @tanstack/react-query:test:lib
  • pnpm exec nx run @tanstack/react-query:test:types (TS 5.4–6.0)
  • pnpm exec nx run @tanstack/react-query:test:eslint
  • pnpm exec nx run @tanstack/vue-query:test:lib
  • pnpm exec nx run @tanstack/vue-query:test:types (TS 5.4–6.0)
  • pnpm exec nx run @tanstack/vue-query:test:eslint
  • pnpm exec nx run @tanstack/{preact,solid,svelte,angular-query-experimental,query-persist-client-core}:test:types

Test plan

  • Unit + type tests pass on all supported TS versions
  • Existing TData should depend from only arguments, not the result ts-expect-error test (ensures NoInfer still blocks reverse inference) keeps erroring
  • Changeset added (patch for @tanstack/query-core and @tanstack/vue-query)

Generated by Ora Studio
Vibe coded by ousamabenyounes

Summary by CodeRabbit

  • Bug Fixes

    • Replaced a custom type handling with TypeScript’s built-in NoInfer to fix assignability in generic/indexed-access contexts.
  • Tests

    • Added TypeScript-only regression tests to verify generic inference and indexed-access behavior.
  • Chores

    • Published a patch release and added a release note documenting the fix.

Generated by Ora Studio (with Claude Code)
Vibe coded by Ben Younes Ousama

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 26, 2026

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6d27a949-1f3e-4915-a69f-10b5f97cf42f

📥 Commits

Reviewing files that changed from the base of the PR and between 011141d and 60991bf.

📒 Files selected for processing (7)
  • .changeset/query-core-noinfer-builtin.md
  • packages/preact-query/src/useQuery.ts
  • packages/query-core/src/queryClient.ts
  • packages/query-core/src/types.ts
  • packages/react-query/src/__tests__/useQuery.test-d.tsx
  • packages/react-query/src/useQuery.ts
  • packages/vue-query/src/queryClient.ts
💤 Files with no reviewable changes (2)
  • packages/query-core/src/types.ts
  • packages/query-core/src/queryClient.ts
✅ Files skipped from review due to trivial changes (1)
  • .changeset/query-core-noinfer-builtin.md
🚧 Files skipped from review as they are similar to previous changes (4)
  • packages/react-query/src/useQuery.ts
  • packages/preact-query/src/useQuery.ts
  • packages/vue-query/src/queryClient.ts
  • packages/react-query/src/tests/useQuery.test-d.tsx

📝 Walkthrough

Walkthrough

Removes a custom NoInfer<T> export from @tanstack/query-core, strips NoInfer from type-only imports across packages, adds an explicit generic on super.setQueryData<TData>(...) in Vue, adds a TypeScript regression test for indexed-access generics, and creates a changeset entry.

Changes

NoInfer removal and propagation

Layer / File(s) Summary
Data Shape
packages/query-core/src/types.ts
Removed exported NoInfer<T> type alias from core types.
Core Import Cleanup
packages/query-core/src/queryClient.ts
Removed NoInfer from ./types type imports used by the core query client.
Caller Imports
packages/react-query/src/useQuery.ts, packages/preact-query/src/useQuery.ts
Consolidated type-only imports and removed NoInfer from import lists.
Vue Delegation
packages/vue-query/src/queryClient.ts
Delegation updated to call super.setQueryData<TData>(...) with explicit TData; removed unused NoInfer import.
Tests
packages/react-query/src/__tests__/useQuery.test-d.tsx
Added TypeScript-only regression test ensuring useQuery preserves indexed-access generic TData inference.
Release Documentation
.changeset/query-core-noinfer-builtin.md
New changeset entry documenting the fix and switching to TypeScript built-in NoInfer (TS ≥ 5.4), referencing issue #9937.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 I nudged a type from the knoll,
and let the builtin take control.
Generics now hop in line,
inference settled, feeling fine.
🎉

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: replacing a custom NoInfer implementation with TypeScript's built-in NoInfer for proper handling of generic indexed-access types.
Description check ✅ Passed The PR description includes comprehensive sections covering root cause, fix details, verification steps, and links the PR to issue #9937, matching the template requirements.
Linked Issues check ✅ Passed The PR fully addresses issue #9937 by replacing the custom NoInfer tuple-index implementation with TypeScript's intrinsic NoInfer, fixing the generic indexed-access type assignment error and restoring code ergonomics.
Out of Scope Changes check ✅ Passed All changes are in-scope: removing custom NoInfer, updating imports across query packages, fixing vue-query's super.setQueryData call, and adding regression tests for the indexed-access TData scenario.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@nx-cloud
Copy link
Copy Markdown

nx-cloud Bot commented Apr 26, 2026

View your CI Pipeline Execution ↗ for commit 60991bf

Command Status Duration Result
nx affected --targets=test:sherif,test:knip,tes... ✅ Succeeded 4m 25s View ↗
nx run-many --target=build --exclude=examples/*... ✅ Succeeded 1s View ↗

☁️ Nx Cloud last updated this comment at 2026-05-07 09:20:11 UTC

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented Apr 26, 2026

More templates

@tanstack/angular-query-experimental

npm i https://pkg.pr.new/@tanstack/angular-query-experimental@10593

@tanstack/eslint-plugin-query

npm i https://pkg.pr.new/@tanstack/eslint-plugin-query@10593

@tanstack/preact-query

npm i https://pkg.pr.new/@tanstack/preact-query@10593

@tanstack/preact-query-devtools

npm i https://pkg.pr.new/@tanstack/preact-query-devtools@10593

@tanstack/preact-query-persist-client

npm i https://pkg.pr.new/@tanstack/preact-query-persist-client@10593

@tanstack/query-async-storage-persister

npm i https://pkg.pr.new/@tanstack/query-async-storage-persister@10593

@tanstack/query-broadcast-client-experimental

npm i https://pkg.pr.new/@tanstack/query-broadcast-client-experimental@10593

@tanstack/query-core

npm i https://pkg.pr.new/@tanstack/query-core@10593

@tanstack/query-devtools

npm i https://pkg.pr.new/@tanstack/query-devtools@10593

@tanstack/query-persist-client-core

npm i https://pkg.pr.new/@tanstack/query-persist-client-core@10593

@tanstack/query-sync-storage-persister

npm i https://pkg.pr.new/@tanstack/query-sync-storage-persister@10593

@tanstack/react-query

npm i https://pkg.pr.new/@tanstack/react-query@10593

@tanstack/react-query-devtools

npm i https://pkg.pr.new/@tanstack/react-query-devtools@10593

@tanstack/react-query-next-experimental

npm i https://pkg.pr.new/@tanstack/react-query-next-experimental@10593

@tanstack/react-query-persist-client

npm i https://pkg.pr.new/@tanstack/react-query-persist-client@10593

@tanstack/solid-query

npm i https://pkg.pr.new/@tanstack/solid-query@10593

@tanstack/solid-query-devtools

npm i https://pkg.pr.new/@tanstack/solid-query-devtools@10593

@tanstack/solid-query-persist-client

npm i https://pkg.pr.new/@tanstack/solid-query-persist-client@10593

@tanstack/svelte-query

npm i https://pkg.pr.new/@tanstack/svelte-query@10593

@tanstack/svelte-query-devtools

npm i https://pkg.pr.new/@tanstack/svelte-query-devtools@10593

@tanstack/svelte-query-persist-client

npm i https://pkg.pr.new/@tanstack/svelte-query-persist-client@10593

@tanstack/vue-query

npm i https://pkg.pr.new/@tanstack/vue-query@10593

@tanstack/vue-query-devtools

npm i https://pkg.pr.new/@tanstack/vue-query-devtools@10593

commit: 60991bf

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
packages/react-query/src/__tests__/useQuery.test-d.tsx (1)

382-382: Optional: assert the test scenario more directly.

expectTypeOf(Test).toBeFunction() is essentially a no-op that exists to keep Test referenced. Since the regression you're guarding against is purely compile-time (the body of Test failing to type-check), the it block compiling is the real assertion. You could either drop the assertion (the function's existence already guards the regression) or assert something more meaningful, e.g. that the data inside Test's body is assignable to DataTypeToEntity[TDataType] | undefined. Not blocking.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/react-query/src/__tests__/useQuery.test-d.tsx` at line 382, The
current test only references Test via expectTypeOf(Test).toBeFunction(), which
is a weak/no-op; replace or strengthen it by asserting the compile-time
assignment you care about: inside the test suite replace the
expectTypeOf(Test).toBeFunction() line with a type assertion that the local
variable used in Test (named data) is assignable to DataTypeToEntity[TDataType]
| undefined (or drop the assertion entirely and rely on the test body
compiling), e.g. use TypeScript's expectType or similar utility to assert data
is of type DataTypeToEntity[TDataType] | undefined so the regression is guarded
by an explicit compile-time check of data's type.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/react-query/src/__tests__/useQuery.test-d.tsx`:
- Around line 341-384: The new describe block describe('generic indexed access
TData', …) is incorrectly nested inside describe('initialData', …); move the
entire describe('generic indexed access TData', ...) block so it is a sibling of
describe('initialData') under the top-level describe('useQuery', …) (i.e., close
the initialData describe before this new describe). Concretely, relocate the
describe block (the entire chunk containing enum DataType, DataTypeToEntity,
getData, getLabel, function Test, and the expectTypeOf assertion) to be placed
after the closing brace of describe('initialData', …) so it sits at the same
level as initialData and not inside it.

---

Nitpick comments:
In `@packages/react-query/src/__tests__/useQuery.test-d.tsx`:
- Line 382: The current test only references Test via
expectTypeOf(Test).toBeFunction(), which is a weak/no-op; replace or strengthen
it by asserting the compile-time assignment you care about: inside the test
suite replace the expectTypeOf(Test).toBeFunction() line with a type assertion
that the local variable used in Test (named data) is assignable to
DataTypeToEntity[TDataType] | undefined (or drop the assertion entirely and rely
on the test body compiling), e.g. use TypeScript's expectType or similar utility
to assert data is of type DataTypeToEntity[TDataType] | undefined so the
regression is guarded by an explicit compile-time check of data's type.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2268aa9f-4f19-4ae2-8111-03e4fb810e30

📥 Commits

Reviewing files that changed from the base of the PR and between 51ef23f and e9172ef.

📒 Files selected for processing (5)
  • .changeset/query-core-noinfer-builtin.md
  • packages/query-core/src/noInfer.ts
  • packages/query-core/src/types.ts
  • packages/react-query/src/__tests__/useQuery.test-d.tsx
  • packages/vue-query/src/queryClient.ts

Comment thread packages/react-query/src/__tests__/useQuery.test-d.tsx Outdated
@ousamabenyounes
Copy link
Copy Markdown
Contributor Author

Thanks @coderabbitai — addressed in d942386. Lifted describe('generic indexed access TData', ...) out of describe('initialData', ...) so it now sits at describe('useQuery', ...) level. Test output groups it correctly. Verified with pnpm exec nx run @tanstack/react-query:test:types, test:lib and test:eslint — all green.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 26, 2026

Tip

For best results, initiate chat on the files or code changes.

@ousamabenyounes: Thanks for the update — moving the describe('generic indexed access TData', ...) block to the top-level describe('useQuery', ...) scope is exactly the right placement, and it's great that the full type/lib/eslint test matrix came back green. Appreciate the thorough verification! 🎉


🧠 Learnings used
Learnt from: sukvvon
Repo: TanStack/query PR: 9892
File: packages/solid-query-persist-client/src/__tests__/PersistQueryClientProvider.test.tsx:331-335
Timestamp: 2025-11-22T09:06:05.219Z
Learning: In TanStack/query test files, when a queryFn contains side effects (e.g., setting flags for test verification), prefer async/await syntax for clarity; when there are no side effects, prefer the .then() pattern for conciseness.

Learnt from: ousamabenyounes
Repo: TanStack/query PR: 0
File: :0-0
Timestamp: 2026-04-26T07:26:42.601Z
Learning: In `packages/solid-query/src/useQueries.ts` (TanStack/query), the per-query proxy / `createResource` path iterates the reactive `state` store as an array (e.g., `queryResults.map` at line 256). When `combine` returns a non-array object shape, this throws `TypeError: queryResults.map is not a function` unconditionally at runtime. The type-level fix in PR `#10577` (relaxing `TCombinedResult extends object`) covers only the TypeScript constraint; the runtime resource-path rework to support non-array `combine` returns is explicitly deferred and tracked in issue `#7522`.

Learnt from: byungsker
Repo: TanStack/query PR: 10465
File: packages/vue-query/src/__tests__/queryOptions.test-d.ts:292-300
Timestamp: 2026-04-13T15:15:51.168Z
Learning: In `packages/vue-query/src/queryOptions.ts`, the predicate form of `enabled` — i.e., `(query) => boolean` — is not supported by `queryOptions` (throws a TypeScript error). This is a pre-existing limitation that exists even on the main branch, unrelated to any specific PR. It is distinct from the simple getter form `() => boolean` which is supported. Predicate support in `queryOptions` would require a separate feature implementation.

Learnt from: ousamabenyounes
Repo: TanStack/query PR: 0
File: :0-0
Timestamp: 2026-04-25T22:35:09.256Z
Learning: In `packages/vue-query/src/useBaseQuery.ts`, the `suspense` method in `UseBaseQueryReturnType` should be declared **outside** the distributive conditional type and typed as `Promise<TResult>` (not pinned to `Promise<QueryObserverResult<TData, TError>>`). This preserves the parameterized observer shape for callers using specialized variants like `DefinedQueryObserverResult` (non-undefined `data`) and `InfiniteQueryObserverResult` (`fetchNextPage`/`hasNextPage`/`data.pages`), and aligns with the runtime value returned by `observer.fetchOptimistic()`.

Learnt from: oscartbeaumont
Repo: TanStack/query PR: 9564
File: packages/solid-query-devtools/src/production.tsx:2-3
Timestamp: 2025-08-19T03:18:18.303Z
Learning: In the solid-query-devtools package, the codebase uses a pattern of type-only default imports combined with typeof for component type annotations (e.g., `import type SolidQueryDevtoolsComp from './devtools'` followed by `typeof SolidQueryDevtoolsComp`). This pattern is consistently used across index.tsx and production.tsx files, and the maintainers prefer consistency over changing this approach.

If you found this review helpful, would you consider giving us a shout-out on X?

Thank you for using CodeRabbit!

@ousamabenyounes
Copy link
Copy Markdown
Contributor Author

Thanks @coderabbitai — addressed the optional nit in 24c74b9. Tried strengthening with both expectTypeOf(data).toEqualTypeOf<DataTypeToEntity[TDataType] | undefined>() and .toMatchTypeOf<...>() — both fail to compile because vitest's type-relation checks reduce to Extends<NoInfer<T>, T> which TS leaves unresolved under the generic TDataType extends DataType constraint.

Per your suggestion ("the function's existence already guards the regression"), kept the implicit assertion (getLabel(props.dataType, data) must compile) and added a short comment documenting the intent so future readers don't mistake it for a no-op.

Type tests + lint all green locally.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 26, 2026

Tip

For best results, initiate chat on the files or code changes.

@ousamabenyounes: That's a solid explanation — the Extends<NoInfer<T>, T> resolution failure under TDataType extends DataType is a known limitation of vitest's type helpers in generic contexts, and it means toEqualTypeOf/toMatchTypeOf are genuinely off the table here without a concrete instantiation. The implicit compile-time assertion (getLabel(props.dataType, data) must compile, plus the explanatory comment) is the right call: it's exactly as strong as anything vitest can offer in this scenario, and future maintainers will now understand why it's not a dead-code no-op.

🐇 ~ inspecting types in a generic burrow ~
   (\ /)
   ( •.•)  NoInfer[T]?
   (> 🔍 <) TS says "¯\_(ツ)_/¯"
   — but the compile passes, and that's enough.

✏️ Learnings added
Learnt from: ousamabenyounes
URL: https://github.com/TanStack/query/pull/10593

Timestamp: 2026-04-26T09:14:54.328Z
Learning: In `packages/react-query/src/__tests__/useQuery.test-d.tsx` (TanStack/query), when writing type tests for `useQuery` with a generic indexed-access `TData` (e.g., `DataTypeToEntity[TDataType]`), `expectTypeOf(data).toEqualTypeOf<DataTypeToEntity[TDataType] | undefined>()` and `.toMatchTypeOf<...>()` both fail to compile because vitest's type-relation helpers reduce to `Extends<NoInfer<T>, T>`, which TypeScript leaves unresolved under the `TDataType extends DataType` generic constraint. The correct approach is to rely on the implicit compile-time assertion — i.e., passing `data` into a function that accepts `DataTypeToEntity[TDataType]` (such as `getLabel(props.dataType, data)`) — and document the intent with a comment so future readers do not mistake it for a no-op.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: ousamabenyounes
Repo: TanStack/query PR: 0
File: :0-0
Timestamp: 2026-04-26T07:26:42.601Z
Learning: In `packages/solid-query/src/useQueries.ts` (TanStack/query), the per-query proxy / `createResource` path iterates the reactive `state` store as an array (e.g., `queryResults.map` at line 256). When `combine` returns a non-array object shape, this throws `TypeError: queryResults.map is not a function` unconditionally at runtime. The type-level fix in PR `#10577` (relaxing `TCombinedResult extends object`) covers only the TypeScript constraint; the runtime resource-path rework to support non-array `combine` returns is explicitly deferred and tracked in issue `#7522`.

Learnt from: ousamabenyounes
Repo: TanStack/query PR: 0
File: :0-0
Timestamp: 2026-04-25T22:35:09.256Z
Learning: In `packages/vue-query/src/useBaseQuery.ts`, the `suspense` method in `UseBaseQueryReturnType` should be declared **outside** the distributive conditional type and typed as `Promise<TResult>` (not pinned to `Promise<QueryObserverResult<TData, TError>>`). This preserves the parameterized observer shape for callers using specialized variants like `DefinedQueryObserverResult` (non-undefined `data`) and `InfiniteQueryObserverResult` (`fetchNextPage`/`hasNextPage`/`data.pages`), and aligns with the runtime value returned by `observer.fetchOptimistic()`.

Learnt from: sukvvon
Repo: TanStack/query PR: 9892
File: packages/solid-query-persist-client/src/__tests__/PersistQueryClientProvider.test.tsx:331-335
Timestamp: 2025-11-22T09:06:05.219Z
Learning: In TanStack/query test files, when a queryFn contains side effects (e.g., setting flags for test verification), prefer async/await syntax for clarity; when there are no side effects, prefer the .then() pattern for conciseness.

Learnt from: oscartbeaumont
Repo: TanStack/query PR: 9564
File: packages/solid-query-devtools/src/production.tsx:2-3
Timestamp: 2025-08-19T03:18:18.303Z
Learning: In the solid-query-devtools package, the codebase uses a pattern of type-only default imports combined with typeof for component type annotations (e.g., `import type SolidQueryDevtoolsComp from './devtools'` followed by `typeof SolidQueryDevtoolsComp`). This pattern is consistently used across index.tsx and production.tsx files, and the maintainers prefer consistency over changing this approach.

Learnt from: byungsker
Repo: TanStack/query PR: 10465
File: packages/vue-query/src/__tests__/queryOptions.test-d.ts:292-300
Timestamp: 2026-04-13T15:15:51.168Z
Learning: In `packages/vue-query/src/queryOptions.ts`, the predicate form of `enabled` — i.e., `(query) => boolean` — is not supported by `queryOptions` (throws a TypeScript error). This is a pre-existing limitation that exists even on the main branch, unrelated to any specific PR. It is distinct from the simple getter form `() => boolean` which is supported. Predicate support in `queryOptions` would require a separate feature implementation.

Comment thread packages/query-core/src/types.ts Outdated
@ousamabenyounes
Copy link
Copy Markdown
Contributor Author

@TkDodo done — dropped the public NoInfer<T> re-export entirely in 011141d and let consumers + internals use TypeScript's intrinsic NoInfer directly. Also removed the ./noInfer.ts shim since it's no longer needed. Type tests + lint + lib tests pass on TS 5.4–6.0 across query-core, react-query, vue-query, preact-query, solid-query, svelte-query, angular-query-experimental, query-persist-client-core.

ousamabenyounes and others added 4 commits May 7, 2026 08:49
…ss types

The local `NoInfer<T> = [T][T extends any ? 0 : never]` trick breaks down
when `T` is a generic indexed-access type such as `DataTypeToEntity[DT]`,
producing errors like "Type '[DataTypeToEntity[DT]]' is not assignable to
type 'DataTypeToEntity'".

Since the project already requires TypeScript >= 5.4, delegate the public
`NoInfer<T>` alias to TypeScript's built-in `NoInfer` (introduced in 5.4).
A small `noInfer.ts` helper exposes it as `IntrinsicNoInfer<T>` to avoid
the local-shadow recursion problem.

Vue's `setQueryData` implementation now forwards the `<TData>` generic to
`super.setQueryData<TData>(...)` so its declared `NoInfer<TData> | undefined`
return type stays satisfied under the stricter built-in `NoInfer`.

Fixes TanStack#9937
…f 'initialData'

Block was nested inside `describe('initialData', ...)` but is unrelated
to initialData behavior. Lift it to sibling level under
`describe('useQuery', ...)` so test output groups it correctly.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…exed-access NoInfer

Per CodeRabbit nitpick: clarify that the `getLabel(props.dataType, data)` call
itself is the regression guard. With the previous hand-rolled NoInfer, this
call failed to type-check; with built-in NoInfer (TS 5.4+), it compiles.

An explicit `expectTypeOf(data).toEqualTypeOf<...>()` / `toMatchTypeOf<...>()`
cannot work here — vitest's type-relation checks reduce to
`Extends<NoInfer<T>, T>` which TS leaves unresolved under a generic
`TDataType extends DataType` constraint.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Per @TkDodo's review: TypeScript's intrinsic NoInfer (TS ≥ 5.4) is the
canonical type, and the package already requires TS ≥ 5.4. Removing the
re-export sidesteps the self-shadowing issue entirely and avoids
encouraging consumers to import a duplicate.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

NoInfer around TData causes TS error with object type

2 participants