diff --git a/.npmignore b/.npmignore new file mode 100644 index 00000000..451a5a6b --- /dev/null +++ b/.npmignore @@ -0,0 +1 @@ +src/*.type-test.ts diff --git a/docs/reference/functions/checkIdField.md b/docs/reference/functions/checkIdField.md index 82d7c5a9..36a6563b 100644 --- a/docs/reference/functions/checkIdField.md +++ b/docs/reference/functions/checkIdField.md @@ -6,9 +6,9 @@ # Function: checkIdField() -> **checkIdField**(`options`): `any` +> **checkIdField**(`options`): `string` \| `undefined` -Defined in: [src/index.ts:47](https://github.com/FirebaseExtended/reactfire/blob/main/src/index.ts#L47) +Defined in: [src/index.ts:49](https://github.com/FirebaseExtended/reactfire/blob/main/src/index.ts#L49) ## Parameters @@ -18,4 +18,4 @@ Defined in: [src/index.ts:47](https://github.com/FirebaseExtended/reactfire/blob ## Returns -`any` +`string` \| `undefined` diff --git a/docs/reference/functions/checkOptions.md b/docs/reference/functions/checkOptions.md index 4f4fdaf0..ce0923b0 100644 --- a/docs/reference/functions/checkOptions.md +++ b/docs/reference/functions/checkOptions.md @@ -6,9 +6,9 @@ # Function: checkOptions() -> **checkOptions**(`options`, `field`): `any` +> **checkOptions**(`options`, `field`): `unknown` -Defined in: [src/index.ts:34](https://github.com/FirebaseExtended/reactfire/blob/main/src/index.ts#L34) +Defined in: [src/index.ts:36](https://github.com/FirebaseExtended/reactfire/blob/main/src/index.ts#L36) ## Parameters @@ -22,4 +22,4 @@ Defined in: [src/index.ts:34](https://github.com/FirebaseExtended/reactfire/blob ## Returns -`any` +`unknown` diff --git a/docs/reference/functions/checkinitialData.md b/docs/reference/functions/checkinitialData.md index f2c78405..96792dcb 100644 --- a/docs/reference/functions/checkinitialData.md +++ b/docs/reference/functions/checkinitialData.md @@ -6,9 +6,9 @@ # Function: checkinitialData() -> **checkinitialData**(`options`): `any` +> **checkinitialData**(`options`): `unknown` -Defined in: [src/index.ts:43](https://github.com/FirebaseExtended/reactfire/blob/main/src/index.ts#L43) +Defined in: [src/index.ts:45](https://github.com/FirebaseExtended/reactfire/blob/main/src/index.ts#L45) ## Parameters @@ -18,4 +18,4 @@ Defined in: [src/index.ts:43](https://github.com/FirebaseExtended/reactfire/blob ## Returns -`any` +`unknown` diff --git a/docs/reference/interfaces/ReactFireOptions.md b/docs/reference/interfaces/ReactFireOptions.md index 7ca63c5e..0503ebb7 100644 --- a/docs/reference/interfaces/ReactFireOptions.md +++ b/docs/reference/interfaces/ReactFireOptions.md @@ -30,7 +30,7 @@ Defined in: [src/index.ts:25](https://github.com/FirebaseExtended/reactfire/blob ### initialData? -> `optional` **initialData?**: `any` +> `optional` **initialData?**: `T` Defined in: [src/index.ts:26](https://github.com/FirebaseExtended/reactfire/blob/main/src/index.ts#L26) @@ -38,7 +38,7 @@ Defined in: [src/index.ts:26](https://github.com/FirebaseExtended/reactfire/blob ### ~~startWithValue?~~ -> `optional` **startWithValue?**: `any` +> `optional` **startWithValue?**: `T` Defined in: [src/index.ts:30](https://github.com/FirebaseExtended/reactfire/blob/main/src/index.ts#L30) diff --git a/docs/reference/interfaces/SignInCheckOptionsBasic.md b/docs/reference/interfaces/SignInCheckOptionsBasic.md index 6c9f2d66..425e0439 100644 --- a/docs/reference/interfaces/SignInCheckOptionsBasic.md +++ b/docs/reference/interfaces/SignInCheckOptionsBasic.md @@ -41,7 +41,7 @@ Defined in: [src/index.ts:25](https://github.com/FirebaseExtended/reactfire/blob ### initialData? -> `optional` **initialData?**: `any` +> `optional` **initialData?**: [`SigninCheckResult`](../type-aliases/SigninCheckResult.md) Defined in: [src/index.ts:26](https://github.com/FirebaseExtended/reactfire/blob/main/src/index.ts#L26) @@ -53,7 +53,7 @@ Defined in: [src/index.ts:26](https://github.com/FirebaseExtended/reactfire/blob ### ~~startWithValue?~~ -> `optional` **startWithValue?**: `any` +> `optional` **startWithValue?**: [`SigninCheckResult`](../type-aliases/SigninCheckResult.md) Defined in: [src/index.ts:30](https://github.com/FirebaseExtended/reactfire/blob/main/src/index.ts#L30) diff --git a/docs/reference/interfaces/SignInCheckOptionsClaimsObject.md b/docs/reference/interfaces/SignInCheckOptionsClaimsObject.md index 092cde82..8407e95a 100644 --- a/docs/reference/interfaces/SignInCheckOptionsClaimsObject.md +++ b/docs/reference/interfaces/SignInCheckOptionsClaimsObject.md @@ -40,7 +40,7 @@ Defined in: [src/index.ts:25](https://github.com/FirebaseExtended/reactfire/blob ### initialData? -> `optional` **initialData?**: `any` +> `optional` **initialData?**: [`SigninCheckResult`](../type-aliases/SigninCheckResult.md) Defined in: [src/index.ts:26](https://github.com/FirebaseExtended/reactfire/blob/main/src/index.ts#L26) @@ -60,7 +60,7 @@ Defined in: [src/auth.tsx:88](https://github.com/FirebaseExtended/reactfire/blob ### ~~startWithValue?~~ -> `optional` **startWithValue?**: `any` +> `optional` **startWithValue?**: [`SigninCheckResult`](../type-aliases/SigninCheckResult.md) Defined in: [src/index.ts:30](https://github.com/FirebaseExtended/reactfire/blob/main/src/index.ts#L30) diff --git a/docs/reference/interfaces/SignInCheckOptionsClaimsValidator.md b/docs/reference/interfaces/SignInCheckOptionsClaimsValidator.md index 83517d7a..914cb6ac 100644 --- a/docs/reference/interfaces/SignInCheckOptionsClaimsValidator.md +++ b/docs/reference/interfaces/SignInCheckOptionsClaimsValidator.md @@ -40,7 +40,7 @@ Defined in: [src/index.ts:25](https://github.com/FirebaseExtended/reactfire/blob ### initialData? -> `optional` **initialData?**: `any` +> `optional` **initialData?**: [`SigninCheckResult`](../type-aliases/SigninCheckResult.md) Defined in: [src/index.ts:26](https://github.com/FirebaseExtended/reactfire/blob/main/src/index.ts#L26) @@ -52,7 +52,7 @@ Defined in: [src/index.ts:26](https://github.com/FirebaseExtended/reactfire/blob ### ~~startWithValue?~~ -> `optional` **startWithValue?**: `any` +> `optional` **startWithValue?**: [`SigninCheckResult`](../type-aliases/SigninCheckResult.md) Defined in: [src/index.ts:30](https://github.com/FirebaseExtended/reactfire/blob/main/src/index.ts#L30) diff --git a/src/firestore.tsx b/src/firestore.tsx index d5efa8bd..7fbb1c79 100644 --- a/src/firestore.tsx +++ b/src/firestore.tsx @@ -63,7 +63,7 @@ export function useFirestoreDocData(ref: DocumentReference, opti const idField = options ? checkIdField(options) : undefined; const observableId = `firestore:docData:${ref.firestore.app.name}:${ref.path}:idField=${JSON.stringify(idField)}`; - const observable = docData(ref, { idField }); + const observable = docData(ref, { idField: idField as keyof T }); return useObservable(observableId, observable, options) as ObservableStatus; } @@ -75,7 +75,7 @@ export function useFirestoreDocDataOnce(ref: DocumentReference, const idField = options ? checkIdField(options) : undefined; const observableId = `firestore:docDataOnce:${ref.firestore.app.name}:${ref.path}:idField=${JSON.stringify(idField)}`; - const observable$ = docData(ref, { idField }).pipe(first()); + const observable$ = docData(ref, { idField: idField as keyof T }).pipe(first()); return useObservable(observableId, observable$, options) as ObservableStatus; } @@ -96,7 +96,7 @@ export function useFirestoreCollection(query: FirestoreQuery(query: FirestoreQuery, options?: ReactFireOptions): ObservableStatus { const idField = options ? checkIdField(options) : undefined; const observableId = `firestore:collectionData:${getUniqueIdForFirestoreQuery(query)}:idField=${JSON.stringify(idField)}`; - const observable$ = collectionData(query, { idField }); + const observable$ = collectionData(query, { idField: idField as (string & keyof T) }); return useObservable(observableId, observable$, options); } diff --git a/src/index.ts b/src/index.ts index ab60a1fe..5a4f2b36 100644 --- a/src/index.ts +++ b/src/index.ts @@ -23,14 +23,16 @@ export class ReactFireError extends Error { export interface ReactFireOptions { idField?: string; - initialData?: T | any; + initialData?: T; /** * @deprecated use initialData instead */ - startWithValue?: T | any; + startWithValue?: T; suspense?: boolean; } +// Deprecated: unused internally as of the ReactFireOptions generic tightening. +// Kept as exports to avoid a breaking removal; slated for removal in v5. export function checkOptions(options: ReactFireOptions, field: string) { // make sure the field passed in is a valid key of ReactFire Options if (field === 'idField' || field === 'initialData' || field === 'suspense') { @@ -44,8 +46,8 @@ export function checkinitialData(options: ReactFireOptions) { return checkOptions(options, 'initialData'); } -export function checkIdField(options: ReactFireOptions) { - return checkOptions(options, 'idField'); +export function checkIdField(options: ReactFireOptions): string | undefined { + return options?.idField; } export * from './auth'; diff --git a/src/reactfire-options.type-test.ts b/src/reactfire-options.type-test.ts new file mode 100644 index 00000000..739b141a --- /dev/null +++ b/src/reactfire-options.type-test.ts @@ -0,0 +1,18 @@ +/** + * Type-level regression tests for ReactFireOptions generic constraints. + * Checked by `tsc --noEmit` in CI. No runtime behavior — not bundled. + */ +import type { ReactFireOptions } from './index'; + +// ---- initialData must match T ---- + +void ((): ReactFireOptions => ({ initialData: 'hello' }))(); +void ((): ReactFireOptions => ({ initialData: 42 }))(); + +// @ts-expect-error initialData must be T, not a different type +const _wrongInitialData: ReactFireOptions = { initialData: 123 }; +void _wrongInitialData; + +// @ts-expect-error startWithValue must be T, not a different type +const _wrongStartWithValue: ReactFireOptions = { startWithValue: 123 }; +void _wrongStartWithValue;