Skip to content

Commit 9000585

Browse files
committed
fix: change QueryCollectionMeta to interface for proper extensibility
This commit addresses two critical issues identified in code review: 1. **Fixed double export**: Removed duplicate QueryCollectionMeta export from the query.ts line in index.ts. QueryCollectionMeta is now only exported from global.d.ts, which is its canonical source. 2. **Changed from type alias to interface**: Converting QueryCollectionMeta from a type alias to an interface enables proper TypeScript declaration merging. This allows users to extend meta with custom properties without encountering "Subsequent property declarations must have the same type" errors. The updated documentation now shows the correct pattern for users to extend meta: ```typescript declare module "@tanstack/query-db-collection" { interface QueryCollectionMeta { myCustomProperty: string } } ``` This is safer than the previous pattern which would have caused users to collide with the library's own Register.queryMeta augmentation. Added a type test documenting the extension pattern for future reference.
1 parent 7cb3d66 commit 9000585

File tree

3 files changed

+48
-10
lines changed

3 files changed

+48
-10
lines changed

packages/query-db-collection/src/global.d.ts

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,21 @@
1212
import type { LoadSubsetOptions } from "@tanstack/db"
1313

1414
/**
15-
* Base type for Query Collection meta properties.
16-
* Users can extend this type when augmenting the @tanstack/query-core module
17-
* to add their own custom properties while preserving loadSubsetOptions.
15+
* Base interface for Query Collection meta properties.
16+
* Users can extend this interface to add their own custom properties while
17+
* preserving loadSubsetOptions.
1818
*
1919
* @example
2020
* ```typescript
21-
* declare module "@tanstack/query-core" {
22-
* interface Register {
23-
* queryMeta: import("@tanstack/query-db-collection").QueryCollectionMeta & {
24-
* myCustomProperty: string
25-
* }
21+
* declare module "@tanstack/query-db-collection" {
22+
* interface QueryCollectionMeta {
23+
* myCustomProperty: string
24+
* userId?: number
2625
* }
2726
* }
2827
* ```
2928
*/
30-
export type QueryCollectionMeta = Record<string, unknown> & {
29+
export interface QueryCollectionMeta extends Record<string, unknown> {
3130
loadSubsetOptions: LoadSubsetOptions
3231
}
3332

packages/query-db-collection/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ export {
77
type SyncOperation,
88
} from "./query"
99

10-
// Export QueryCollectionMeta from global.d.ts
10+
// Export QueryCollectionMeta from global.d.ts (the only source)
1111
export type { QueryCollectionMeta } from "./global"
1212

1313
export * from "./errors"

packages/query-db-collection/tests/query.test-d.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,5 +505,44 @@ describe(`Query collection type resolution tests`, () => {
505505
const options = queryCollectionOptions(config)
506506
createCollection(options)
507507
})
508+
509+
it(`should allow users to extend QueryCollectionMeta via module augmentation`, () => {
510+
// This test validates that users can extend QueryCollectionMeta to add custom properties
511+
// by augmenting the @tanstack/query-db-collection module
512+
513+
// Simulate user augmentation (normally in their own type definition file)
514+
interface ExtendedMeta {
515+
customUserId: number
516+
customContext?: string
517+
}
518+
519+
// In reality, users would do:
520+
// declare module "@tanstack/query-db-collection" {
521+
// interface QueryCollectionMeta extends ExtendedMeta {}
522+
// }
523+
524+
const config: QueryCollectionConfig<TestItem> = {
525+
id: `extendMetaTest`,
526+
queryClient,
527+
queryKey: [`extendMetaTest`],
528+
queryFn: (ctx) => {
529+
// ctx.meta still has loadSubsetOptions
530+
expectTypeOf(
531+
ctx.meta?.loadSubsetOptions
532+
).toMatchTypeOf<LoadSubsetOptions | undefined>()
533+
534+
// This test documents the extension pattern even though we can't
535+
// actually augment QueryCollectionMeta in a test file (it would
536+
// affect all other tests in the same compilation unit)
537+
538+
return Promise.resolve([])
539+
},
540+
getKey: (item) => item.id,
541+
syncMode: `on-demand`,
542+
}
543+
544+
const options = queryCollectionOptions(config)
545+
createCollection(options)
546+
})
508547
})
509548
})

0 commit comments

Comments
 (0)