Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 115 additions & 0 deletions packages/firestore/lib/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,105 @@ export namespace FirebaseFirestoreTypes {
[key: string]: any;
}

/**
* Allows FieldValues to be passed in as a property value while maintaining
* type safety.
*/
export type WithFieldValue<T> =
| T
| (T extends Primitive
? T
: T extends object
? { [K in keyof T]: WithFieldValue<T[K]> | FieldValue }
: never);

/**
* Similar to Typescript's `Partial<T>`, but allows nested fields to be
* omitted and FieldValues to be passed in as property values.
*/
export type PartialWithFieldValue<T> =
| Partial<T>
| (T extends Primitive
? T
: T extends object
? { [K in keyof T]?: PartialWithFieldValue<T[K]> | FieldValue }
: never);

/**
* Converter used by `withConverter()` to transform user objects of type
* `AppModelType` into Firestore data of type `DbModelType`.
*
* Using the converter allows you to specify generic type arguments when
* storing and retrieving objects from Firestore.
*
* In this context, an "AppModel" is a class that is used in an application to
* package together related information and functionality. Such a class could,
* for example, have properties with complex, nested data types, properties
* used for memoization, properties of types not supported by Firestore (such
* as `symbol` and `bigint`), and helper functions that perform compound
* operations. Such classes are not suitable and/or possible to store into a
* Firestore database. Instead, instances of such classes need to be converted
* to "plain old JavaScript objects" (POJOs) with exclusively primitive
* properties, potentially nested inside other POJOs or arrays of POJOs. In
* this context, this type is referred to as the "DbModel" and would be an
* object suitable for persisting into Firestore. For convenience,
* applications can implement `FirestoreDataConverter` and register the
* converter with Firestore objects, such as `DocumentReference` or `Query`,
* to automatically convert `AppModel` to `DbModel` when storing into
* Firestore, and convert `DbModel` to `AppModel` when retrieving from
* Firestore.
*/
export interface FirestoreDataConverter<
AppModelType,
DbModelType extends DocumentData = DocumentData,
> {
/**
* Converts a custom model object of type
* `AppModelType` into a plain Javascript object (suitable for writing
* directly to the Firestore database) of type `DbModelType`.
*
* To use set() with `merge` and `mergeFields`,
* toFirestore() must be defined with `Partial<T>`.
*
* The `WithFieldValue<T>` type extends `T` to also allow FieldValues such
* as `FieldValue.delete()` to be used as property values.
*/
toFirestore(modelObject: WithFieldValue<AppModelType>): WithFieldValue<DbModelType>;

/**
* Converts a custom model object of type
* `AppModelType` into a plain Javascript object (suitable for writing
* directly to the Firestore database) of type `DbModelType`.
*
* To use set() with `merge` and `mergeFields`,
* toFirestore() must be defined with `Partial<T>`.
*
* The `PartialWithFieldValue<T>` type extends `Partial<T>` to allow
* FieldValues such as `FieldValue.delete()` to be used as property values.
* It also supports nested `Partial` by allowing nested fields to be
* omitted.
*/
toFirestore(
modelObject: PartialWithFieldValue<AppModelType>,
options: SetOptions,
): PartialWithFieldValue<DbModelType>;

/**
* Called by the Firestore SDK to convert Firestore data into an object of
* type `AppModelType`. You can access your data by calling:
* `snapshot.data()`.
*
* Generally, the data returned from `snapshot.data()` can be cast to
* `DbModelType`; however, this is not guaranteed because Firestore does not
* enforce a schema on the database. For example, writes from a previous
* version of the application or writes from another client that did not use
* a type converter could have written data with different properties and/or
* property types. The implementation will need to choose whether to
* gracefully recover from non-conforming data or throw an error.
*/
fromFirestore(snapshot: QueryDocumentSnapshot): AppModelType;
}

/**
* A `CollectionReference` object can be used for adding documents, getting document references, and querying for
* documents (using the methods inherited from `Query`).
Expand Down Expand Up @@ -194,6 +293,22 @@ export namespace FirebaseFirestoreTypes {
* @param documentPath A slash-separated path to a document.
*/
doc(documentPath?: string): DocumentReference<T>;

/**
* Applies a custom data converter to this CollectionReference, allowing you
* to use your own custom model objects with Firestore. When you call add()
* on the returned CollectionReference instance, the provided converter will
* convert between Firestore data of type `NewDbModelType` and your custom
* type `NewAppModelType`.
*
* @param converter Converts objects to and from Firestore. Passing in
* `null` removes the current converter.
* @return A CollectionReference that uses the provided converter.
*/
withConverter<NewAppModelType, NewDbModelType extends DocumentData = DocumentData>(
converter: FirestoreDataConverter<NewAppModelType>,
): CollectionReference<NewAppModelType, NewDbModelType>;
withConverter(converter: null): CollectionReference;
}

/**
Expand Down
26 changes: 2 additions & 24 deletions packages/firestore/lib/modular/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,14 @@ import DocumentData = FirebaseFirestoreTypes.DocumentData;
import Query = FirebaseFirestoreTypes.Query;
import FieldValue = FirebaseFirestoreTypes.FieldValue;
import FieldPath = FirebaseFirestoreTypes.FieldPath;
import PartialWithFieldValue = FirebaseFirestoreTypes.PartialWithFieldValue;
import WithFieldValue = FirebaseFirestoreTypes.WithFieldValue;
import PersistentCacheIndexManager = FirebaseFirestoreTypes.PersistentCacheIndexManager;
import AggregateQuerySnapshot = FirebaseFirestoreTypes.AggregateQuerySnapshot;

/** Primitive types. */
export type Primitive = string | number | boolean | undefined | null;

/**
* Similar to Typescript's `Partial<T>`, but allows nested fields to be
* omitted and FieldValues to be passed in as property values.
*/
export type PartialWithFieldValue<T> =
| Partial<T>
| (T extends Primitive
? T
: T extends object
? { [K in keyof T]?: PartialWithFieldValue<T[K]> | FieldValue }
: never);

/**
* Given a union type `U = T1 | T2 | ...`, returns an intersected type (`T1 & T2 & ...`).
*
Expand Down Expand Up @@ -84,18 +74,6 @@ export declare type UpdateData<T> = T extends Primitive
} & NestedUpdateFields<T>
: Partial<T>;

/**
* Allows FieldValues to be passed in as a property value while maintaining
* type safety.
*/
export type WithFieldValue<T> =
| T
| (T extends Primitive
? T
: T extends object
? { [K in keyof T]: WithFieldValue<T[K]> | FieldValue }
: never);

export type EmulatorMockTokenOptions = ({ user_id: string } | { sub: string }) &
Partial<FirebaseIdToken>;

Expand Down