persistedCollectionOptions: schema type parameter not inferred, result incompatible with createCollection

Open Beginner friendly
#1,452 1 comment 8 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
68/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Quiet
Tech stack
typescript
Domain
api

Research direction

Start at persistedCollectionOptions and compare its overloads with the schema-aware patterns in packages/db/src/local-only.ts. Verify both sync-present and sync-absent cases preserve the schema type and that the returned options can be passed to createCollection; done when the reproduction infers the schema and type-checks.

Written by the indexing model from the issue text.

Description

  • I've validated the bug against the latest version of DB packages

Describe the bug

When passing a schema to persistedCollectionOptions, TypeScript fails to infer the TSchema type parameter. This causes two problems:

  1. Schema type not inferred: options.schema resolves to undefined instead of the actual schema type (e.g. a Zod schema). TSchema defaults to never.
  2. Incompatible with createCollection: The result cannot be passed to createCollection because:
    • createCollection's schema overloads require { schema: T } (required)
    • createCollection's no-schema overloads require { schema?: never }
    • The result has schema?: TSchema | undefined (optional), which matches neither

Root cause

persistedCollectionOptions lacks schema-aware overloads. Compare with localOnlyCollectionOptions (which works correctly) — it has separate overloads for the schema and no-schema cases with & { schema: T } / & { schema?: never } on both input and output types.

persistedCollectionOptions only has two overloads (sync-present vs sync-absent), neither of which distinguishes the schema case.

To Reproduce

import { z } from 'zod'
import { createCollection } from '@tanstack/db'
import { persistedCollectionOptions } from '@tanstack/db-sqlite-persistence-core'

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

const adapter = {
  loadSubset: () => Promise.resolve([]),
  applyCommittedTx: () => Promise.resolve(),
  ensureIndex: () => Promise.resolve(),
}

// TSchema defaults to `never` — schema type is lost
const options = persistedCollectionOptions({
  id: 'test',
  schema: todoSchema,
  schemaVersion: 1,
  getKey: (item) => item.id,
  persistence: { adapter },
})

// options.schema is `undefined` instead of `typeof todoSchema`

// This errors: "No overload matches this call"
const collection = createCollection(options)

Expected behavior

persistedCollectionOptions should infer the schema type and produce a result compatible with createCollection, matching the behavior of localOnlyCollectionOptions.

Additional context

The fix requires adding schema-aware overloads to persistedCollectionOptions (for both sync-present and sync-absent modes), following the same pattern used by localOnlyCollectionOptions in packages/db/src/local-only.ts.

Dominant language
TypeScript
Stars
3.9k
Forks
266
Avg merge
1d 4h
Merged PRs (30d)
52

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from TanStack/db

All issues in TanStack/db

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.