Skip to content

fix(db): restore query typechecking for generic collection row types#1678

Merged
KyleAMathews merged 3 commits into
TanStack:mainfrom
obeattie:test/issue-1677-generic-row-type
Jul 16, 2026
Merged

fix(db): restore query typechecking for generic collection row types#1678
KyleAMathews merged 3 commits into
TanStack:mainfrom
obeattie:test/issue-1677-generic-row-type

Conversation

@obeattie

@obeattie obeattie commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

This restores TypeScript query-builder support for collections whose row type is an unresolved generic parameter. Generic where, select, and subquery join-source callbacks once again expose fields guaranteed by the generic constraint, fixing the regression introduced in v0.6.6.

Root cause

The query builder decides whether a callback value should be represented as a property-bearing Ref or an opaque RefLeaf through a conditional type. For an unresolved generic such as T extends { id: string }, the conditional was deferred into a union containing both possibilities. Because RefLeaf has no row properties, TypeScript rejected access to fields such as id even though the generic constraint guarantees them.

Subquery sources had an additional mapped Prettify layer that prevented TypeScript from resolving the generic constraint through the ref conditional.

Approach

  • Make RefForContextValue distributive so TypeScript can evaluate the ref shape through the generic constraint.
  • Use the unwrapped GetRawResult for internal subquery schemas, while retaining GetResult for final user-facing result types.
  • Add type regressions for direct where, direct select, and generic subqueries used as join sources.

Key invariants

  • A constraint such as T extends { id: string } must expose id inside supported query callbacks.
  • Concrete result types retain their existing IDE-friendly presentation.
  • The internal schema change does not alter runtime query behavior.

Non-goals

This PR restores the three cases reported in #1677. Broader generic-constraint propagation through nullable joined aliases and both forms of unionAll is tracked separately in #1679; resolving those cases safely requires additional type-system work and must preserve existing heterogeneous union and join inference.

Trade-offs

GetRawResult is used only on the internal subquery schema path. Final results continue to use the prettified representation, avoiding a user-facing type-display regression.

Verification

The new type tests were added first and verified RED against the regressed implementation, then GREEN after the fix.

pnpm --filter @tanstack/db test

Files changed

  • packages/db/src/query/builder/types.ts — preserves generic constraints through callback ref and subquery schema construction.
  • packages/db/tests/query/generic-collection.test-d.ts — covers generic filtering, selection, and subquery join sources.
  • .changeset/generic-row-type-refs.md — records the patch release impact.

Fixes #1677

Follow-up: #1679

obeattie and others added 3 commits July 16, 2026 18:08
…nStack#1677)

Queries over a Collection<T> where T is an unresolved generic type
parameter stopped typechecking in 0.6.6: refs inside where/join/select
callbacks resolve to a union including RefLeaf, which exposes no row
properties, even ones guaranteed by T's constraint.

These tests currently fail and should pass once the ref typing is fixed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Fixes TanStack#1677. Since 0.6.6, refs inside where/join/select callbacks broke
when the collection's row type is an unresolved generic type parameter:
TypeScript defers the IsPlainObject conditional in RefForContextValue and
degrades the ref to a union that includes RefLeaf, which exposes no row
properties.

Two changes:

- Make RefForContextValue distribute over T so that, when deferred,
  TypeScript resolves its constraint by instantiating T with T's own
  constraint, picking the Ref branch instead of the Ref | RefLeaf union.
- Use GetRawResult instead of GetResult in SchemaFromSource for subquery
  sources: GetResult's Prettify wrapper produces a mapped type that the
  conditional-constraint resolution above cannot see through. Final query
  results still go through GetResult, so IDE display is unaffected.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Updates query-builder schema inference for subqueries and adds compile-time regression tests for generic collection row-property access and generic subquery joins. A patch changeset documents the fix.

Changes

Generic collection typing

Layer / File(s) Summary
Subquery schema inference
packages/db/src/query/builder/types.ts
SchemaFromSource now uses GetRawResult<TContext> for QueryBuilder sources; RefForContextValue is reformatted without behavioral changes.
Generic collection regression coverage
packages/db/tests/query/generic-collection.test-d.ts, .changeset/generic-row-type-refs.md
Declaration tests cover constrained id access in where and select callbacks and generic collection subqueries as leftJoin sources; a patch changeset documents the regression fix.

Estimated code review effort: 2 (Simple) | ~10 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The code changes and tests address #1677 by restoring generic collection query typing for where, select, joins, and subquery join sources.
Out of Scope Changes check ✅ Passed The changes are limited to the type fix, regression tests, and changeset, with no unrelated scope visible.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Title check ✅ Passed The title clearly and concisely describes the main fix: restoring query typechecking for generic collection row types.
Description check ✅ Passed The description is comprehensive and covers the change, motivation, testing, release impact, and changeset, though it doesn't follow the template exactly.
✨ 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.

@KyleAMathews KyleAMathews left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Verified the reported #1677 regression and the PR's three type-test cases: generic where callbacks, select callbacks, and generic subqueries used as join sources. The implementation is appropriately scoped and the broader nullable/union constraint-propagation work is now documented in #1679. Approving this as a valid incremental regression fix.

@pkg-pr-new

pkg-pr-new Bot commented Jul 16, 2026

Copy link
Copy Markdown
More templates

@tanstack/angular-db

npm i https://pkg.pr.new/@tanstack/angular-db@1678

@tanstack/browser-db-sqlite-persistence

npm i https://pkg.pr.new/@tanstack/browser-db-sqlite-persistence@1678

@tanstack/capacitor-db-sqlite-persistence

npm i https://pkg.pr.new/@tanstack/capacitor-db-sqlite-persistence@1678

@tanstack/cloudflare-durable-objects-db-sqlite-persistence

npm i https://pkg.pr.new/@tanstack/cloudflare-durable-objects-db-sqlite-persistence@1678

@tanstack/db

npm i https://pkg.pr.new/@tanstack/db@1678

@tanstack/db-ivm

npm i https://pkg.pr.new/@tanstack/db-ivm@1678

@tanstack/db-sqlite-persistence-core

npm i https://pkg.pr.new/@tanstack/db-sqlite-persistence-core@1678

@tanstack/electric-db-collection

npm i https://pkg.pr.new/@tanstack/electric-db-collection@1678

@tanstack/electron-db-sqlite-persistence

npm i https://pkg.pr.new/@tanstack/electron-db-sqlite-persistence@1678

@tanstack/expo-db-sqlite-persistence

npm i https://pkg.pr.new/@tanstack/expo-db-sqlite-persistence@1678

@tanstack/node-db-sqlite-persistence

npm i https://pkg.pr.new/@tanstack/node-db-sqlite-persistence@1678

@tanstack/offline-transactions

npm i https://pkg.pr.new/@tanstack/offline-transactions@1678

@tanstack/powersync-db-collection

npm i https://pkg.pr.new/@tanstack/powersync-db-collection@1678

@tanstack/query-db-collection

npm i https://pkg.pr.new/@tanstack/query-db-collection@1678

@tanstack/react-db

npm i https://pkg.pr.new/@tanstack/react-db@1678

@tanstack/react-native-db-sqlite-persistence

npm i https://pkg.pr.new/@tanstack/react-native-db-sqlite-persistence@1678

@tanstack/rxdb-db-collection

npm i https://pkg.pr.new/@tanstack/rxdb-db-collection@1678

@tanstack/solid-db

npm i https://pkg.pr.new/@tanstack/solid-db@1678

@tanstack/svelte-db

npm i https://pkg.pr.new/@tanstack/svelte-db@1678

@tanstack/tauri-db-sqlite-persistence

npm i https://pkg.pr.new/@tanstack/tauri-db-sqlite-persistence@1678

@tanstack/trailbase-db-collection

npm i https://pkg.pr.new/@tanstack/trailbase-db-collection@1678

@tanstack/vue-db

npm i https://pkg.pr.new/@tanstack/vue-db@1678

commit: e38b48a

@KyleAMathews
KyleAMathews merged commit 8258d09 into TanStack:main Jul 16, 2026
11 checks passed
@github-actions github-actions Bot mentioned this pull request Jul 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Since 0.6.6, queries don't typecheck when the collection's row type is a generic type parameter

2 participants