diff --git a/packages/firestore/lib/FirestoreCollectionReference.ts b/packages/firestore/lib/FirestoreCollectionReference.ts index ed3922f4a7..e429044e4a 100644 --- a/packages/firestore/lib/FirestoreCollectionReference.ts +++ b/packages/firestore/lib/FirestoreCollectionReference.ts @@ -30,11 +30,15 @@ import type FirestorePath from './FirestorePath'; import type { DocumentData, FirestoreDataConverter } from './types/firestore'; import type { FirestoreInternal } from './types/internal'; -export default class CollectionReference extends Query { +export default class CollectionReference< + AppModelType = DocumentData, + DbModelType extends DocumentData = DocumentData, +> extends Query { + readonly type = 'collection' as const; constructor( firestore: FirestoreInternal, collectionPath: FirestorePath, - converter?: FirestoreDataConverter | null, + converter?: FirestoreDataConverter | null, ) { super(firestore, collectionPath, new QueryModifiers(), undefined, converter); } @@ -43,19 +47,19 @@ export default class CollectionReference extends Query { return this._collectionPath.id; } - get parent(): DocumentReference | null { + get parent(): DocumentReference | null { const parent = this._collectionPath.parent(); if (!parent) { return null; } - return new DocumentReference(this._firestore, parent); + return new DocumentReference(this._firestore, parent); } get path(): string { return this._collectionPath.relativeName; } - add(data: Record): Promise { + add(data: AppModelType): Promise> { if (!isObject(data)) { throw new Error("firebase.firestore().collection().add(*) 'data' must be an object."); } @@ -64,7 +68,7 @@ export default class CollectionReference extends Query { return documentRef.set(data).then(() => Promise.resolve(documentRef)); } - doc(documentPath?: string): DocumentReference { + doc(documentPath?: string): DocumentReference { const newPath = documentPath ?? generateFirestoreId(); const path = this._collectionPath.child(newPath); @@ -74,12 +78,24 @@ export default class CollectionReference extends Query { ); } - return new DocumentReference(this._firestore, path, this._converter); + return new DocumentReference(this._firestore, path, this._converter); } - withConverter(converter: unknown): CollectionReference { + withConverter(converter: null): CollectionReference; + withConverter( + converter: FirestoreDataConverter, + ): CollectionReference; + withConverter( + converter: FirestoreDataConverter | null | unknown, + ): + | CollectionReference + | CollectionReference { if (isUndefined(converter) || isNull(converter)) { - return new CollectionReference(this._firestore, this._collectionPath, null); + return new CollectionReference( + this._firestore, + this._collectionPath, + null, + ); } try { @@ -88,10 +104,10 @@ export default class CollectionReference extends Query { throw new Error(`firebase.firestore().collection().withConverter() ${(e as Error).message}`); } - return new CollectionReference( + return new CollectionReference( this._firestore, this._collectionPath, - converter as FirestoreDataConverter, + converter as FirestoreDataConverter, ); } } diff --git a/packages/firestore/lib/FirestoreDocumentReference.ts b/packages/firestore/lib/FirestoreDocumentReference.ts index c3e4971ec0..cbdb046a34 100644 --- a/packages/firestore/lib/FirestoreDocumentReference.ts +++ b/packages/firestore/lib/FirestoreDocumentReference.ts @@ -78,17 +78,21 @@ export function provideDocumentSnapshotClass( let _id = 0; -export default class DocumentReference { +export default class DocumentReference< + AppModelType = DocumentData, + DbModelType extends DocumentData = DocumentData, +> { + readonly type = 'document' as const; _firestore: FirestoreInternal; _documentPath: FirestorePath; - _converter: FirestoreDataConverter | null; + _converter: FirestoreDataConverter | null; constructor(firestore: FirestoreInternal, documentPath: FirestorePath, converter?: unknown) { this._firestore = firestore; this._documentPath = documentPath; this._converter = (converter === undefined ? null : converter) as FirestoreDataConverter< - DocumentData, - DocumentData + AppModelType, + DbModelType > | null; } @@ -96,7 +100,7 @@ export default class DocumentReference { return this._firestore; } - get converter(): unknown { + get converter(): FirestoreDataConverter | null { return this._converter; } @@ -106,7 +110,11 @@ export default class DocumentReference { get parent(): FirestoreCollectionReferenceClass { const parentPath = this._documentPath.parent(); - return new FirestoreCollectionReference!(this._firestore, parentPath!, this._converter); + return new FirestoreCollectionReference!( + this._firestore, + parentPath!, + this._converter as unknown as FirestoreDataConverter | null, + ); } get path(): string { @@ -141,7 +149,9 @@ export default class DocumentReference { return this._firestore.native.documentDelete(this.path); } - get(options?: { source?: 'default' | 'server' | 'cache' }): Promise { + get(options?: { + source?: 'default' | 'server' | 'cache'; + }): Promise> { if (!isUndefined(options) && !isObject(options)) { throw new Error("firebase.firestore().doc().get(*) 'options' must be an object is provided."); } @@ -166,13 +176,16 @@ export default class DocumentReference { new FirestoreDocumentSnapshotClass!( this._firestore, data as DocumentSnapshotNativeData, - this._converter, + this._converter as unknown as FirestoreDataConverter< + DocumentData, + DocumentData + > | null, ), - ) as DocumentSnapshot, + ) as DocumentSnapshot, ); } - isEqual(other: DocumentReference): boolean { + isEqual(other: DocumentReference): boolean { if (!(other instanceof DocumentReference)) { throw new Error( "firebase.firestore().doc().isEqual(*) 'other' expected a DocumentReference instance.", @@ -189,8 +202,11 @@ export default class DocumentReference { onSnapshot(...args: unknown[]): () => void { let snapshotListenOptions: { includeMetadataChanges?: boolean }; - let callback: (snapshot: DocumentSnapshot | null, error: Error | null) => void; - let onNext: (snapshot: DocumentSnapshot) => void; + let callback: ( + snapshot: DocumentSnapshot | null, + error: Error | null, + ) => void; + let onNext: (snapshot: DocumentSnapshot) => void; let onError: (error: Error) => void; try { @@ -203,7 +219,7 @@ export default class DocumentReference { throw new Error(`firebase.firestore().doc().onSnapshot(*) ${(e as Error).message}`); } - function handleSuccess(documentSnapshot: DocumentSnapshot): void { + function handleSuccess(documentSnapshot: DocumentSnapshot): void { callback(documentSnapshot, null); onNext(documentSnapshot); } @@ -224,8 +240,15 @@ export default class DocumentReference { const snapshot = event.body.snapshot; if (!snapshot) return; const documentSnapshot = createDeprecationProxy( - new FirestoreDocumentSnapshotClass!(this._firestore, snapshot, this._converter), - ); + new FirestoreDocumentSnapshotClass!( + this._firestore, + snapshot, + this._converter as unknown as FirestoreDataConverter< + DocumentData, + DocumentData + > | null, + ), + ) as DocumentSnapshot; handleSuccess(documentSnapshot); } }, @@ -290,11 +313,21 @@ export default class DocumentReference { ); } - withConverter( - converter: FirestoreDataConverter | null, - ): DocumentReference { + withConverter(converter: null): DocumentReference; + withConverter( + converter: FirestoreDataConverter, + ): DocumentReference; + withConverter( + converter: FirestoreDataConverter | null, + ): + | DocumentReference + | DocumentReference { if (isUndefined(converter) || isNull(converter)) { - return new DocumentReference(this._firestore, this._documentPath, null); + return new DocumentReference( + this._firestore, + this._documentPath, + null, + ); } try { @@ -303,7 +336,11 @@ export default class DocumentReference { throw new Error(`firebase.firestore().doc().withConverter() ${(e as Error).message}`); } - return new DocumentReference(this._firestore, this._documentPath, converter); + return new DocumentReference( + this._firestore, + this._documentPath, + converter, + ); } } diff --git a/packages/firestore/lib/FirestoreDocumentSnapshot.ts b/packages/firestore/lib/FirestoreDocumentSnapshot.ts index f456e8a526..6f1d558a99 100644 --- a/packages/firestore/lib/FirestoreDocumentSnapshot.ts +++ b/packages/firestore/lib/FirestoreDocumentSnapshot.ts @@ -32,6 +32,7 @@ import type { DocumentData, DocumentSnapshot as DocumentSnapshotDeclare, FirestoreDataConverter, + QueryDocumentSnapshot, } from './types/firestore'; export interface DocumentSnapshotNativeData { @@ -41,27 +42,34 @@ export interface DocumentSnapshotNativeData { exists?: boolean; } -export default class DocumentSnapshot { +export default class DocumentSnapshot< + AppModelType = DocumentData, + DbModelType extends DocumentData = DocumentData, +> { _firestore: FirestoreInternal; _nativeData: DocumentSnapshotNativeData; _data: Record | undefined; _metadata: SnapshotMetadata; - _ref: DocumentReference; + _ref: DocumentReference; _exists: boolean; - _converter: FirestoreDataConverter | null; + _converter: FirestoreDataConverter | null; constructor( firestore: FirestoreInternal, nativeData: DocumentSnapshotNativeData, - converter: FirestoreDataConverter | null, + converter: FirestoreDataConverter | null, ) { this._firestore = firestore; this._nativeData = nativeData; + this._converter = converter; this._data = parseNativeMap(firestore, nativeData.data as Record | undefined); this._metadata = new SnapshotMetadata(nativeData.metadata ?? [false, false]); - this._ref = new DocumentReference(firestore, FirestorePath.fromName(nativeData.path)); + this._ref = new DocumentReference( + firestore, + FirestorePath.fromName(nativeData.path), + this._converter, + ); this._exists = nativeData.exists ?? false; - this._converter = converter; } get id(): string { @@ -72,32 +80,32 @@ export default class DocumentSnapshot { return this._metadata; } - get ref(): DocumentReference { + get ref(): DocumentReference { return this._ref; } - exists(): boolean { + exists(): this is QueryDocumentSnapshot { return this._exists; } - data(options?: SnapshotOptions): DocumentData | undefined { + data(options?: SnapshotOptions): AppModelType | undefined { if (this._converter) { try { return (this._converter as ConverterWithFromFirestoreInternal).fromFirestore( - new DocumentSnapshot( + new DocumentSnapshot( this._firestore, this._nativeData, null, ) as unknown as DocumentSnapshotDeclare, options, - ) as DocumentData; + ) as AppModelType; } catch (e) { throw new Error( `firebase.firestore() DocumentSnapshot.data(*) 'withConverter.fromFirestore' threw an error: ${(e as Error).message}.`, ); } } - return this._data; + return this._data as AppModelType | undefined; } get(fieldPath: string | FieldPath, _options?: SnapshotOptions): DocumentFieldValueInternal { @@ -124,7 +132,7 @@ export default class DocumentSnapshot { return extractFieldPathData(this._data, path._segments) as DocumentFieldValueInternal; } - isEqual(other: DocumentSnapshot): boolean { + isEqual(other: DocumentSnapshot): boolean { if (!(other instanceof DocumentSnapshot)) { throw new Error( "firebase.firestore() DocumentSnapshot.isEqual(*) 'other' expected a DocumentSnapshot instance.", diff --git a/packages/firestore/lib/FirestoreQuery.ts b/packages/firestore/lib/FirestoreQuery.ts index 94449cfc31..5330c1a10c 100644 --- a/packages/firestore/lib/FirestoreQuery.ts +++ b/packages/firestore/lib/FirestoreQuery.ts @@ -44,22 +44,25 @@ import type { let _id = 0; -export default class Query { +export default class Query< + AppModelType = DocumentData, + DbModelType extends DocumentData = DocumentData, +> { _firestore: FirestoreInternal; _collectionPath: FirestorePath; _modifiers: QueryModifiers; _queryName: string | undefined; - _converter: FirestoreDataConverter | null; + _converter: FirestoreDataConverter | null; /** Satisfies Query for AggregateQuerySnapshot and similar. */ - readonly type = 'query' as const; + readonly type: 'query' | 'collection' = 'query'; constructor( firestore: FirestoreInternal, collectionPath: FirestorePath, modifiers: QueryModifiers, queryName?: string, - converter?: FirestoreDataConverter | null, + converter?: FirestoreDataConverter | null, ) { this._firestore = firestore; this._collectionPath = collectionPath; @@ -72,13 +75,13 @@ export default class Query { return this._firestore; } - get converter(): FirestoreDataConverter | null { + get converter(): FirestoreDataConverter | null { return this._converter; } _handleQueryCursor( cursor: 'startAt' | 'startAfter' | 'endAt' | 'endBefore', - docOrField: DocumentSnapshot | DocumentFieldValueInternal, + docOrField: DocumentSnapshot | DocumentFieldValueInternal, fields: DocumentFieldValueInternal[], ): QueryModifiers { const modifiers = this._modifiers._copy(); @@ -172,7 +175,12 @@ export default class Query { count(): ReturnType { return createDeprecationProxy( - new AggregateQuery(this._firestore, this, this._collectionPath, this._modifiers), + new AggregateQuery( + this._firestore, + this as unknown as Query, + this._collectionPath, + this._modifiers, + ), ); } @@ -188,7 +196,11 @@ export default class Query { new Query( this._firestore, this._collectionPath, - this._handleQueryCursor('endAt', docOrField, filterModularArgument(fields)), + this._handleQueryCursor( + 'endAt', + docOrField as DocumentSnapshot | DocumentFieldValueInternal, + filterModularArgument(fields), + ), this._queryName, this._converter, ), @@ -203,14 +215,20 @@ export default class Query { new Query( this._firestore, this._collectionPath, - this._handleQueryCursor('endBefore', docOrField, filterModularArgument(fields)), + this._handleQueryCursor( + 'endBefore', + docOrField as DocumentSnapshot | DocumentFieldValueInternal, + filterModularArgument(fields), + ), this._queryName, this._converter, ), ); } - get(options?: { source?: 'default' | 'server' | 'cache' }): Promise { + get(options?: { + source?: 'default' | 'server' | 'cache'; + }): Promise> { if (!isUndefined(options) && !isObject(options)) { throw new Error( "firebase.firestore().collection().get(*) 'options' must be an object is provided.", @@ -272,7 +290,7 @@ export default class Query { ); } - isEqual(other: Query): boolean { + isEqual(other: Query): boolean { if (!(other instanceof Query)) { throw new Error( "firebase.firestore().collection().isEqual(*) 'other' expected a Query instance.", @@ -332,8 +350,11 @@ export default class Query { onSnapshot(...args: unknown[]): () => void { let snapshotListenOptions: { includeMetadataChanges?: boolean }; - let callback: (snapshot: QuerySnapshot | null, error: Error | null) => void; - let onNext: (snapshot: QuerySnapshot) => void; + let callback: ( + snapshot: QuerySnapshot | null, + error: Error | null, + ) => void; + let onNext: (snapshot: QuerySnapshot) => void; let onError: (error: Error) => void; this._modifiers.validatelimitToLast(); @@ -348,7 +369,7 @@ export default class Query { throw new Error(`firebase.firestore().collection().onSnapshot(*) ${(e as Error).message}`); } - function handleSuccess(querySnapshot: QuerySnapshot): void { + function handleSuccess(querySnapshot: QuerySnapshot): void { callback(querySnapshot, null); onNext(querySnapshot); } @@ -464,7 +485,7 @@ export default class Query { } startAfter( - docOrField: DocumentSnapshot | DocumentFieldValueInternal, + docOrField: DocumentSnapshot | DocumentFieldValueInternal, ...fields: DocumentFieldValueInternal[] ): ReturnType { return createDeprecationProxy( @@ -479,7 +500,7 @@ export default class Query { } startAt( - docOrField: DocumentSnapshot | DocumentFieldValueInternal, + docOrField: DocumentSnapshot | DocumentFieldValueInternal, ...fields: DocumentFieldValueInternal[] ): ReturnType { return createDeprecationProxy( @@ -586,11 +607,15 @@ export default class Query { ); } - withConverter( - converter: FirestoreDataConverter | null | unknown, - ): Query { + withConverter(converter: null): Query; + withConverter( + converter: FirestoreDataConverter, + ): Query; + withConverter( + converter: FirestoreDataConverter | null | unknown, + ): Query | Query { if (isUndefined(converter) || isNull(converter)) { - return new Query( + return new Query( this._firestore, this._collectionPath, this._modifiers, @@ -605,12 +630,12 @@ export default class Query { throw new Error(`firebase.firestore().collection().withConverter() ${(e as Error).message}`); } - return new Query( + return new Query( this._firestore, this._collectionPath, this._modifiers, this._queryName, - converter as FirestoreDataConverter, + converter as FirestoreDataConverter, ); } } diff --git a/packages/firestore/lib/FirestoreQuerySnapshot.ts b/packages/firestore/lib/FirestoreQuerySnapshot.ts index bab2561cd5..16e5f2769f 100644 --- a/packages/firestore/lib/FirestoreQuerySnapshot.ts +++ b/packages/firestore/lib/FirestoreQuerySnapshot.ts @@ -49,33 +49,43 @@ export interface QuerySnapshotNativeData { metadata: [boolean, boolean]; } -export default class QuerySnapshot { - _query: Query; +export default class QuerySnapshot< + AppModelType = DocumentData, + DbModelType extends DocumentData = DocumentData, +> { + _query: Query; _source: string | undefined; _excludesMetadataChanges: boolean | undefined; _changes: DocumentChange[]; - _docs: DocumentSnapshot[]; + _docs: DocumentSnapshot[]; _metadata: SnapshotMetadata; constructor( firestore: FirestoreInternal, - query: Query, + query: Query, nativeData: QuerySnapshotNativeData, - converter: FirestoreDataConverter | null, + converter: FirestoreDataConverter | null, ) { this._query = query; this._source = nativeData.source; this._excludesMetadataChanges = nativeData.excludesMetadataChanges; this._changes = nativeData.changes.map( - (c: QuerySnapshotNativeData['changes'][0]) => new DocumentChange(firestore, c, converter), + (c: QuerySnapshotNativeData['changes'][0]) => + new DocumentChange( + firestore, + c, + converter as unknown as FirestoreDataConverter | null, + ), ); this._docs = nativeData.documents.map((doc: QuerySnapshotNativeData['documents'][0]) => - createDeprecationProxy(new DocumentSnapshot(firestore, doc, converter)), - ) as DocumentSnapshot[]; + createDeprecationProxy( + new DocumentSnapshot(firestore, doc, converter), + ), + ) as DocumentSnapshot[]; this._metadata = new SnapshotMetadata(nativeData.metadata ?? [false, false]); } - get docs(): DocumentSnapshot[] { + get docs(): DocumentSnapshot[] { return this._docs; } @@ -87,7 +97,7 @@ export default class QuerySnapshot { return this._metadata; } - get query(): Query { + get query(): Query { return this._query; } @@ -132,7 +142,10 @@ export default class QuerySnapshot { }); } - forEach(callback: (doc: DocumentSnapshot, index: number) => void, thisArg?: unknown): void { + forEach( + callback: (doc: DocumentSnapshot, index: number) => void, + thisArg?: unknown, + ): void { if (!isFunction(callback)) { throw new Error( "firebase.firestore() QuerySnapshot.forEach(*) 'callback' expected a function.", @@ -146,7 +159,7 @@ export default class QuerySnapshot { } } - isEqual(other: QuerySnapshot, ...args: unknown[]): boolean { + isEqual(other: QuerySnapshot, ...args: unknown[]): boolean { if (!(other instanceof QuerySnapshot)) { throw new Error( "firebase.firestore() QuerySnapshot.isEqual(*) 'other' expected a QuerySnapshot instance.", diff --git a/packages/firestore/lib/FirestoreTransaction.ts b/packages/firestore/lib/FirestoreTransaction.ts index 547fd0be66..1ac5ce9dc8 100644 --- a/packages/firestore/lib/FirestoreTransaction.ts +++ b/packages/firestore/lib/FirestoreTransaction.ts @@ -22,7 +22,14 @@ import type { DocumentSnapshotNativeData } from './FirestoreDocumentSnapshot'; import { parseSetOptions, parseUpdateArgs, applyFirestoreDataConverter } from './utils'; import { buildNativeMap } from './utils/serialize'; import type { FirestoreInternal } from './types/internal'; -import type { SetOptions } from './types/firestore'; +import type { + DocumentData, + DocumentReference as DocumentReferenceType, + DocumentSnapshot as DocumentSnapshotType, + PartialWithFieldValue, + SetOptions, + WithFieldValue, +} from './types/firestore'; export interface TransactionMeta { id: number; @@ -68,7 +75,9 @@ export default class Transaction { /** * Reads the document referenced by the provided DocumentReference. */ - get(documentRef: DocumentReference): Promise { + get( + documentRef: DocumentReferenceType, + ): Promise> { if (!(documentRef instanceof DocumentReference)) { throw new Error( "firebase.firestore().runTransaction() Transaction.get(*) 'documentRef' expected a DocumentReference.", @@ -78,17 +87,35 @@ export default class Transaction { this._calledGetCount++; return this._firestore.native .transactionGetDocument(this._meta.id, documentRef.path) - .then((data: unknown) => - createDeprecationProxy( - new DocumentSnapshot(this._firestore, data as DocumentSnapshotNativeData, null), - ), + .then( + (data: unknown) => + createDeprecationProxy( + new DocumentSnapshot( + this._firestore, + data as DocumentSnapshotNativeData, + (documentRef as unknown as DocumentReference).converter, + ), + ) as unknown as DocumentSnapshotType, ); } /** * Writes to the document referred to by the provided DocumentReference. */ - set(documentRef: DocumentReference, data: Record, options?: SetOptions): this { + set( + documentRef: DocumentReferenceType, + data: WithFieldValue, + ): this; + set( + documentRef: DocumentReferenceType, + data: PartialWithFieldValue, + options: SetOptions, + ): this; + set( + documentRef: DocumentReferenceType, + data: Record, + options?: SetOptions, + ): this { if (!(documentRef instanceof DocumentReference)) { throw new Error( "firebase.firestore().runTransaction() Transaction.set(*) 'documentRef' expected a DocumentReference.", @@ -129,7 +156,10 @@ export default class Transaction { return this; } - update(documentRef: DocumentReference, ...args: unknown[]): this { + update( + documentRef: DocumentReferenceType, + ...args: unknown[] + ): this { if (!(documentRef instanceof DocumentReference)) { throw new Error( "firebase.firestore().runTransaction() Transaction.update(*) 'documentRef' expected a DocumentReference.", @@ -154,7 +184,9 @@ export default class Transaction { return this; } - delete(documentRef: DocumentReference): this { + delete( + documentRef: DocumentReferenceType, + ): this { if (!(documentRef instanceof DocumentReference)) { throw new Error( "firebase.firestore().runTransaction() Transaction.delete(*) 'documentRef' expected a DocumentReference.", diff --git a/packages/firestore/lib/FirestoreWriteBatch.ts b/packages/firestore/lib/FirestoreWriteBatch.ts index 12711e0efe..0227c98b40 100644 --- a/packages/firestore/lib/FirestoreWriteBatch.ts +++ b/packages/firestore/lib/FirestoreWriteBatch.ts @@ -20,7 +20,13 @@ import DocumentReference from './FirestoreDocumentReference'; import { parseSetOptions, parseUpdateArgs, applyFirestoreDataConverter } from './utils'; import { buildNativeMap } from './utils/serialize'; import type { FirestoreInternal } from './types/internal'; -import type { SetOptions } from './types/firestore'; +import type { + DocumentData, + DocumentReference as DocumentReferenceType, + PartialWithFieldValue, + SetOptions, + WithFieldValue, +} from './types/firestore'; export interface BatchWrite { path: string; @@ -59,7 +65,9 @@ export default class WriteBatch { ); } - delete(documentRef: DocumentReference): this { + delete( + documentRef: DocumentReferenceType, + ): this { this._verifyNotCommitted('delete'); if (!(documentRef instanceof DocumentReference)) { throw new Error( @@ -81,7 +89,20 @@ export default class WriteBatch { return this; } - set(documentRef: DocumentReference, data: Record, options?: SetOptions): this { + set( + documentRef: DocumentReferenceType, + data: WithFieldValue, + ): this; + set( + documentRef: DocumentReferenceType, + data: PartialWithFieldValue, + options: SetOptions, + ): this; + set( + documentRef: DocumentReferenceType, + data: Record, + options?: SetOptions, + ): this { this._verifyNotCommitted('set'); if (!(documentRef instanceof DocumentReference)) { throw new Error( @@ -125,7 +146,10 @@ export default class WriteBatch { return this; } - update(documentRef: DocumentReference, ...args: unknown[]): this { + update( + documentRef: DocumentReferenceType, + ...args: unknown[] + ): this { this._verifyNotCommitted('update'); if (!(documentRef instanceof DocumentReference)) { throw new Error( diff --git a/packages/firestore/lib/index.ts b/packages/firestore/lib/index.ts index 5007ad4642..d2025e2387 100644 --- a/packages/firestore/lib/index.ts +++ b/packages/firestore/lib/index.ts @@ -19,8 +19,6 @@ export * from './modular'; // Export modular/public type helpers. -// DocumentSnapshot, LoadBundleTask, QuerySnapshot, SnapshotMetadata, Transaction, WriteBatch -// are excluded here because they are already exported as values from './modular'. export type { FirebaseApp, Firestore, @@ -61,7 +59,13 @@ export type { Query, CollectionReference, DocumentReference, + DocumentSnapshot, + LoadBundleTask, QueryDocumentSnapshot, + QuerySnapshot, + SnapshotMetadata, + Transaction, + WriteBatch, } from './types/firestore'; // Export namespaced API diff --git a/packages/firestore/type-test.ts b/packages/firestore/type-test.ts index 6b1f442856..1c30250267 100644 --- a/packages/firestore/type-test.ts +++ b/packages/firestore/type-test.ts @@ -78,9 +78,12 @@ import firestore, { CACHE_SIZE_UNLIMITED, AggregateField, AggregateQuerySnapshot, + DocumentSnapshot, DocumentReference, Query, QueryDocumentSnapshot, + Transaction, + WriteBatch, } from '.'; import type { FirebaseFirestoreTypes, @@ -541,6 +544,30 @@ runTransaction(modFirestore1, async tx => { return 'done'; }).then(() => {}); +// Root runtime exports must also carry the generic modular type surface. +function acceptRootDocumentSnapshot(_snap: DocumentSnapshot) {} +function acceptRootTransaction(tx: Transaction, tRef: DocumentReference) { + tx.update(tRef, { active: true }); +} +runTransaction(modFirestore1, async tx => { + const rootTx: Transaction = tx; + const rootSnap: DocumentSnapshot = await rootTx.get(modDoc); + acceptRootDocumentSnapshot(rootSnap); + acceptRootTransaction(rootTx, modDoc); + if (rootSnap.exists()) { + const rootData: DocumentData = rootSnap.data(); + void rootData; + } + return rootSnap; +}).then((rootSnap: DocumentSnapshot) => { + acceptRootDocumentSnapshot(rootSnap); +}); +const rootBatch: WriteBatch = writeBatch(modFirestore1); +rootBatch.update(modDoc, { active: true }); +void acceptRootDocumentSnapshot; +void acceptRootTransaction; +void rootBatch; + // ----- query, where, or, and, orderBy, startAt, startAfter, endAt, endBefore, limit, limitToLast ----- const modQuery1 = query(modColl, where('name', '==', 'test')); const modQuery2 = query(modColl, orderBy('age', 'desc'), limit(10));