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). 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`] 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 + }) +})