Skip to content

Conversation

@KyleAMathews
Copy link
Collaborator

@KyleAMathews KyleAMathews commented Nov 14, 2025

Probably fixes a typescript error.

This fixes a TypeScript error where queryCollectionOptions (and other
collection options functions) produce Collections that TypeScript
reports as missing the compareOptions property.

The issue occurred because:
1. The Collection interface extends CollectionImpl but didn't explicitly
   declare the compareOptions property
2. CollectionImpl has a compareOptions getter, but TypeScript's Pick
   utility (used in CollectionLike) couldn't properly resolve it from
   the interface

The fix explicitly declares compareOptions as a readonly property in
the Collection interface, making it properly accessible for type
checking.

Fixes the issue reported in Discord where users get:
"Type 'Collection<T, string, any, any, any>' is missing properties:
comparisonOpts, compareOptions"

Related to PR #762 which added defaultStringCollation support.
@changeset-bot
Copy link

changeset-bot bot commented Nov 14, 2025

🦋 Changeset detected

Latest commit: 823c7ea

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 11 packages
Name Type
@tanstack/db Patch
@tanstack/angular-db Patch
@tanstack/db-collection-e2e Patch
@tanstack/electric-db-collection Patch
@tanstack/powersync-db-collection Patch
@tanstack/react-db Patch
@tanstack/rxdb-db-collection Patch
@tanstack/solid-db Patch
@tanstack/svelte-db Patch
@tanstack/trailbase-db-collection Patch
@tanstack/vue-db Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pkg-pr-new
Copy link

pkg-pr-new bot commented Nov 14, 2025

More templates

@tanstack/angular-db

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

@tanstack/db

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

@tanstack/db-ivm

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

@tanstack/electric-db-collection

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

@tanstack/offline-transactions

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

@tanstack/powersync-db-collection

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

@tanstack/query-db-collection

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

@tanstack/react-db

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

@tanstack/rxdb-db-collection

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

@tanstack/solid-db

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

@tanstack/svelte-db

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

@tanstack/trailbase-db-collection

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

@tanstack/vue-db

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

commit: 823c7ea

@github-actions
Copy link
Contributor

github-actions bot commented Nov 14, 2025

Size Change: -16 B (-0.02%)

Total Size: 86 kB

Filename Size Change
./packages/db/dist/esm/collection/index.js 3.23 kB -16 B (-0.49%)
ℹ️ View Unchanged
Filename Size
./packages/db/dist/esm/collection/change-events.js 1.38 kB
./packages/db/dist/esm/collection/changes.js 977 B
./packages/db/dist/esm/collection/events.js 388 B
./packages/db/dist/esm/collection/indexes.js 1.1 kB
./packages/db/dist/esm/collection/lifecycle.js 1.67 kB
./packages/db/dist/esm/collection/mutations.js 2.26 kB
./packages/db/dist/esm/collection/state.js 3.43 kB
./packages/db/dist/esm/collection/subscription.js 2.42 kB
./packages/db/dist/esm/collection/sync.js 2.12 kB
./packages/db/dist/esm/deferred.js 207 B
./packages/db/dist/esm/errors.js 4.11 kB
./packages/db/dist/esm/event-emitter.js 748 B
./packages/db/dist/esm/index.js 2.63 kB
./packages/db/dist/esm/indexes/auto-index.js 742 B
./packages/db/dist/esm/indexes/base-index.js 766 B
./packages/db/dist/esm/indexes/btree-index.js 1.87 kB
./packages/db/dist/esm/indexes/lazy-index.js 1.1 kB
./packages/db/dist/esm/indexes/reverse-index.js 513 B
./packages/db/dist/esm/local-only.js 837 B
./packages/db/dist/esm/local-storage.js 2.04 kB
./packages/db/dist/esm/optimistic-action.js 359 B
./packages/db/dist/esm/paced-mutations.js 496 B
./packages/db/dist/esm/proxy.js 3.22 kB
./packages/db/dist/esm/query/builder/functions.js 733 B
./packages/db/dist/esm/query/builder/index.js 3.84 kB
./packages/db/dist/esm/query/builder/ref-proxy.js 917 B
./packages/db/dist/esm/query/compiler/evaluators.js 1.35 kB
./packages/db/dist/esm/query/compiler/expressions.js 691 B
./packages/db/dist/esm/query/compiler/group-by.js 1.8 kB
./packages/db/dist/esm/query/compiler/index.js 1.96 kB
./packages/db/dist/esm/query/compiler/joins.js 2 kB
./packages/db/dist/esm/query/compiler/order-by.js 1.25 kB
./packages/db/dist/esm/query/compiler/select.js 1.07 kB
./packages/db/dist/esm/query/expression-helpers.js 1.43 kB
./packages/db/dist/esm/query/ir.js 673 B
./packages/db/dist/esm/query/live-query-collection.js 360 B
./packages/db/dist/esm/query/live/collection-config-builder.js 5.26 kB
./packages/db/dist/esm/query/live/collection-registry.js 264 B
./packages/db/dist/esm/query/live/collection-subscriber.js 1.77 kB
./packages/db/dist/esm/query/live/internal.js 130 B
./packages/db/dist/esm/query/optimizer.js 2.6 kB
./packages/db/dist/esm/query/predicate-utils.js 2.88 kB
./packages/db/dist/esm/query/subset-dedupe.js 921 B
./packages/db/dist/esm/scheduler.js 1.21 kB
./packages/db/dist/esm/SortedMap.js 1.18 kB
./packages/db/dist/esm/strategies/debounceStrategy.js 237 B
./packages/db/dist/esm/strategies/queueStrategy.js 422 B
./packages/db/dist/esm/strategies/throttleStrategy.js 236 B
./packages/db/dist/esm/transactions.js 2.9 kB
./packages/db/dist/esm/utils.js 881 B
./packages/db/dist/esm/utils/browser-polyfills.js 304 B
./packages/db/dist/esm/utils/btree.js 5.61 kB
./packages/db/dist/esm/utils/comparison.js 852 B
./packages/db/dist/esm/utils/index-optimization.js 1.51 kB
./packages/db/dist/esm/utils/type-guards.js 157 B

compressed-size-action::db-package-size

@github-actions
Copy link
Contributor

github-actions bot commented Nov 14, 2025

Size Change: 0 B

Total Size: 3.34 kB

ℹ️ View Unchanged
Filename Size
./packages/react-db/dist/esm/index.js 225 B
./packages/react-db/dist/esm/useLiveInfiniteQuery.js 1.17 kB
./packages/react-db/dist/esm/useLiveQuery.js 1.11 kB
./packages/react-db/dist/esm/useLiveSuspenseQuery.js 431 B
./packages/react-db/dist/esm/usePacedMutations.js 401 B

compressed-size-action::react-db-package-size

Copy link
Contributor

@kevin-dp kevin-dp left a comment

Choose a reason for hiding this comment

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

After looking into this issue and the proposed fixed, it's not clear to me why the error occurs and why this fixes it. We should add a unit test that reproduces the type error. I tried adding one, but i was not able to reproduce this type error.

I don't like this fix. I would rather turn the compareOptions getter into a true readonly property on the CollectionImpl class instead of having to add it to the extends clause as is done in this fix.

@KyleAMathews
Copy link
Collaborator Author

@kevin-dp we could ask the user to share their code? Also did you try looking at one of the examples?

KyleAMathews and others added 7 commits November 17, 2025 07:43
This fixes a TypeScript error where collections created with
queryCollectionOptions (and other collection option functions) were
incorrectly reported as missing the compareOptions property.

Changes:
1. Converted compareOptions from a getter to a public readonly property
   in CollectionImpl class (per Kevin's suggestion)
2. Removed private comparisonOpts field that was used by the getter
3. Added comprehensive type tests to verify compareOptions is accessible

The issue occurred because TypeScript's Pick utility (used in CollectionLike)
couldn't properly resolve getter properties from extended classes. Making
compareOptions a true readonly property ensures proper type resolution.

Tests added cover three scenarios:
- Collection with queryFn type inference
- Collection with schema
- Collection with explicit type parameter

Fixes the issue reported in Discord where users get:
"Type 'Collection<T, string, any, any, any>' is missing properties:
comparisonOpts, compareOptions"

Related to PR #762 which added defaultStringCollation support.
TypeScript allows setting readonly properties in constructors without
error, so the directive is not needed and causes a build error.
@IARI
Copy link

IARI commented Nov 17, 2025

@KyleAMathews a few days ago on discord you mentioned, that my problem would be related to this.

If that is in fact the case, the TS issue I have is very easy to reproduce @kevin-dp.
Here's a minimal example:

import { z } from 'zod'
import { queryCollectionOptions } from '@tanstack/query-db-collection'
import { QueryClient } from '@tanstack/query-core'

export const queryClient = new QueryClient()

const schema = z
  .object({
    name: z.string().min(1)
  })
  .transform((item) => ({ ...item, id: -1, blubb: 'blubb' }))

const options = queryCollectionOptions({
  queryKey: ['local-test-array'],
  schema,
  queryFn: async () => {
    return [{
        name: 'test',
        id: 0
    }]
  },
  getKey: (item) => item.id,
  queryClient
})

excerpt from pnpm-lock.yaml:

'@tanstack/query-core':
  specifier: ^5.90.10
  version: 5.90.10
'@tanstack/query-db-collection':
  specifier: ^1.0.1
  version: 1.0.1(@tanstack/db@0.5.1(typescript@5.9.3))(@tanstack/query-core@5.90.10)(typescript@5.9.3)
zod:
  specifier: ^4.1.12
  version: 4.1.12
image

Adds a test case that exactly reproduces the Discord bug report where
a user had a Zod schema with .transform() and was getting the error:
'Type Collection<...> is missing properties: comparisonOpts, compareOptions'

This ensures our fix covers this specific edge case.
@KyleAMathews
Copy link
Collaborator Author

@IARI this PR should now fix your issue 👍 I've pushed some changes since @kevin-dp reviewed it earlier

Adjusted the schema transform test to not pass the schema parameter
directly (which causes type issues with ZodEffects), and instead
properly type the queryFn return value. This ensures the test validates
that compareOptions is accessible while working within the current
queryCollectionOptions type constraints.

Also fixed eslint warning by prefixing unused schema variable with _.
@kevin-dp
Copy link
Contributor

kevin-dp commented Nov 18, 2025

The type error that was reported initially seems to be different from the one reported by @IARI. In the future, let's fix separate bugs in separate PRs.

Regarding the original type error, i indeed tried to reproduce it but i couldn't:

const todoSchema = z.object({
  id: z.string(),
  title: z.string(),
  completed: z.boolean(),
})

type Todo = z.infer<typeof todoSchema>

const queryClient = new QueryClient()

const todosCollection = createCollection(
  queryCollectionOptions({
    queryKey: ["todos"],
    queryFn: async () => {
      const response = await fetch("/api/todos")
      return response.json() as Promise<Todo[]>
    },
    queryClient,
    getKey: (item) => item.id,
  })
)

This type checks without errors. Note that i has to change the OP's typecast to return response.json as Promise<Todo[]> because .json() returns a promise.

PS: When fixing a bug let's always introduce a unit test reproducing the bug such that we can be sure the fix actually solves the bug and we don't introduce regressions. In this case, i think we were chasing a bug that does no(t) (longer) exist.

@KyleAMathews KyleAMathews changed the title Fix queryCollectionOptions type error after upgrade use public readonly to make compareOptions readable but not writable Nov 18, 2025
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.

5 participants