diff --git a/.changeset/fix-collection-compare-options-type.md b/.changeset/fix-collection-compare-options-type.md new file mode 100644 index 000000000..e20277264 --- /dev/null +++ b/.changeset/fix-collection-compare-options-type.md @@ -0,0 +1,5 @@ +--- +"@tanstack/db": patch +--- + +Fix Collection compareOptions type error. This resolves a TypeScript error where collections created with `queryCollectionOptions()` (and other collection option functions) were incorrectly reported as missing the `compareOptions` property. The fix converts `compareOptions` from a getter to a public readonly property in the `CollectionImpl` class, ensuring proper type resolution with TypeScript's `Pick` utility. diff --git a/packages/db/src/collection/index.ts b/packages/db/src/collection/index.ts index 5616a8ceb..3abd5cdfb 100644 --- a/packages/db/src/collection/index.ts +++ b/packages/db/src/collection/index.ts @@ -231,7 +231,7 @@ export class CollectionImpl< // and for debugging public _state: CollectionStateManager - private comparisonOpts: StringCollationConfig + public readonly compareOptions: StringCollationConfig /** * Creates a new Collection instance @@ -270,7 +270,7 @@ export class CollectionImpl< this._state = new CollectionStateManager(config) this._sync = new CollectionSyncManager(config, this.id) - this.comparisonOpts = buildCompareOptionsFromConfig(config) + this.compareOptions = buildCompareOptionsFromConfig(config) this._changes.setDeps({ collection: this, // Required for passing to CollectionSubscription @@ -513,11 +513,6 @@ export class CollectionImpl< return this._mutations.validateData(data, type, key) } - get compareOptions(): StringCollationConfig { - // return a copy such that no one can mutate the internal comparison object - return { ...this.comparisonOpts } - } - /** * Inserts one or more items into the collection * @param items - Single item or array of items to insert diff --git a/packages/query-db-collection/tests/query.test-d.ts b/packages/query-db-collection/tests/query.test-d.ts index c8df9298e..09e0ad7fb 100644 --- a/packages/query-db-collection/tests/query.test-d.ts +++ b/packages/query-db-collection/tests/query.test-d.ts @@ -12,6 +12,7 @@ import { queryCollectionOptions } from "../src/query" import type { DeleteMutationFnParams, InsertMutationFnParams, + StringCollationConfig, UpdateMutationFnParams, } from "@tanstack/db" @@ -403,4 +404,114 @@ describe(`Query collection type resolution tests`, () => { expectTypeOf(selectUserData).parameters.toEqualTypeOf<[ResponseType]>() }) }) + + describe(`compareOptions property access`, () => { + it(`should have compareOptions property accessible on collection created with queryCollectionOptions`, () => { + type TodoType = { + id: string + title: string + completed: boolean + } + + const options = queryCollectionOptions({ + queryClient, + queryKey: [`todos`], + queryFn: async (): Promise> => { + return [] as Array + }, + getKey: (item) => item.id, + }) + + const collection = createCollection(options) + + // This should not produce a type error - compareOptions should be accessible + expectTypeOf( + collection.compareOptions + ).toEqualTypeOf() + }) + + it(`should have compareOptions property accessible when using schema`, () => { + const todoSchema = z.object({ + id: z.string(), + title: z.string(), + completed: z.boolean(), + }) + + type TodoType = z.infer + + const options = queryCollectionOptions({ + queryClient, + queryKey: [`todos`], + queryFn: async (): Promise> => { + return [] as Array + }, + schema: todoSchema, + getKey: (item) => item.id, + }) + + const collection = createCollection(options) + + // This should not produce a type error - compareOptions should be accessible + expectTypeOf( + collection.compareOptions + ).toEqualTypeOf() + }) + + it(`should have compareOptions property accessible with schema transform`, () => { + // Reproduces the exact scenario from Discord bug report + const _schema = z + .object({ + name: z.string().min(1), + }) + .transform((item) => ({ ...item, id: -1, blubb: `blubb` })) + + type SchemaOutput = z.infer + + const options = queryCollectionOptions({ + queryKey: [`local-test-array`], + // When using schema with transform, we need to provide the explicit type + queryFn: async (): Promise> => { + return [ + { + name: `test`, + id: 0, + blubb: `blubb`, + }, + ] + }, + getKey: (item) => item.id, + queryClient, + }) + + const collection = createCollection(options) + + // This should not produce a type error - compareOptions should be accessible + // This was the exact error reported: "missing properties: comparisonOpts, compareOptions" + expectTypeOf( + collection.compareOptions + ).toEqualTypeOf() + }) + + it(`should have compareOptions property accessible when using explicit type`, () => { + type TodoType = { + id: string + title: string + completed: boolean + } + + const options = queryCollectionOptions({ + queryClient, + queryKey: [`todos`], + queryFn: async () => [] as Array, + getKey: (item) => item.id, + }) + + const collection = createCollection(options) + + // This should not produce a type error - compareOptions should be accessible + expectTypeOf( + collection.compareOptions + ).toEqualTypeOf() + }) + }) })