From b1d4b47df7af2c5736663e19831b05f11db1c866 Mon Sep 17 00:00:00 2001 From: Oliver Beattie Date: Thu, 16 Jul 2026 18:08:00 +0200 Subject: [PATCH 1/3] test(db): add failing type tests for generic collection row types (#1677) Queries over a Collection 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 --- .../tests/query/generic-collection.test-d.ts | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 packages/db/tests/query/generic-collection.test-d.ts diff --git a/packages/db/tests/query/generic-collection.test-d.ts b/packages/db/tests/query/generic-collection.test-d.ts new file mode 100644 index 000000000..553b5f975 --- /dev/null +++ b/packages/db/tests/query/generic-collection.test-d.ts @@ -0,0 +1,53 @@ +import { describe, test } from 'vitest' +import { createLiveQueryCollection, eq } from '../../src/query/index.js' +import type { Collection } from '../../src/collection/index.js' + +// Regression tests for https://github.com/TanStack/db/issues/1677 +// Queries over a Collection where T is an unresolved generic type parameter +// must still expose the properties guaranteed by T's constraint inside +// where/join/select callbacks. This worked in 0.6.5 and broke in 0.6.6. + +describe(`queries over generic collection row types`, () => { + test(`where callback can access properties guaranteed by the type constraint`, () => { + function findById( + items: Collection, + id: string, + ) { + return createLiveQueryCollection((q) => + q.from({ items }).where(({ items: itemsRef }) => eq(itemsRef.id, id)), + ) + } + + void findById + }) + + test(`select callback can access properties guaranteed by the type constraint`, () => { + function selectIds(items: Collection) { + return createLiveQueryCollection((q) => + q.from({ items }).select(({ items: itemsRef }) => ({ + id: itemsRef.id, + })), + ) + } + + void selectIds + }) + + test(`subquery over a generic collection can be used as a join source`, () => { + function withDiff( + a: Collection, + b: Collection<{ id: string }, string>, + ) { + return createLiveQueryCollection((q) => { + const sub = q.from({ a }) + return q + .from({ b }) + .leftJoin({ sub }, ({ b: bRef, sub: subRef }) => + eq(bRef.id, subRef.id), + ) + }) + } + + void withDiff + }) +}) From 688b9942791aaa7fbd31ebc26f9dc34ad13d9b52 Mon Sep 17 00:00:00 2001 From: Oliver Beattie Date: Thu, 16 Jul 2026 18:25:28 +0200 Subject: [PATCH 2/3] fix(db): restore query typechecking for generic collection row types Fixes #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 --- packages/db/src/query/builder/types.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/db/src/query/builder/types.ts b/packages/db/src/query/builder/types.ts index d8b730e76..f8cdbcabe 100644 --- a/packages/db/src/query/builder/types.ts +++ b/packages/db/src/query/builder/types.ts @@ -117,7 +117,7 @@ export type SchemaFromSource = Prettify<{ [K in keyof T]: T[K] extends CollectionImpl ? InferCollectionType : T[K] extends QueryBuilder - ? GetResult + ? GetRawResult : never }> @@ -662,8 +662,11 @@ type ValueOfUnion = T extends unknown ? T[K] : never : never -type RefForContextValue = - IsPlainObject extends true ? Ref : RefLeaf +type RefForContextValue = T extends unknown + ? IsPlainObject extends true + ? Ref + : RefLeaf + : never type RefsSchemaForContext = IsExactlyUndefined extends true ? TContext[`schema`] From e38b48a1e1aee228c47719b852c7b185dff51373 Mon Sep 17 00:00:00 2001 From: Oliver Beattie Date: Thu, 16 Jul 2026 18:29:49 +0200 Subject: [PATCH 3/3] chore: add changeset for generic row type fix Co-Authored-By: Claude Fable 5 --- .changeset/generic-row-type-refs.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/generic-row-type-refs.md diff --git a/.changeset/generic-row-type-refs.md b/.changeset/generic-row-type-refs.md new file mode 100644 index 000000000..5bac80669 --- /dev/null +++ b/.changeset/generic-row-type-refs.md @@ -0,0 +1,5 @@ +--- +'@tanstack/db': patch +--- + +Fix queries failing to typecheck when the collection's row type is a generic type parameter. Refs inside where/join/select callbacks now expose the properties guaranteed by the type parameter's constraint, and subqueries over generic collections can be used as join sources again (regression introduced in 0.6.6).