FirestoreDataConverter interface

Convertisseur utilisé par withConverter() pour transformer des objets utilisateur de type AppModelType en données Firestore de type DbModelType .

L'utilisation du convertisseur vous permet de spécifier des arguments de type générique lors du stockage et de la récupération d'objets depuis Firestore.

Dans ce contexte, un « AppModel » est une classe utilisée dans une application pour regrouper des informations et des fonctionnalités associées. Une telle classe pourrait, par exemple, avoir des propriétés avec des types de données complexes et imbriqués, des propriétés utilisées pour la mémorisation, des propriétés de types non pris en charge par Firestore (tels que symbol et bigint . ) et des fonctions d'assistance qui effectuent des opérations composées. De telles classes ne sont pas adaptées et/ou ne peuvent pas être stockées dans une base de données Firestore. Au lieu de cela, les instances de ces classes doivent être converties en « objets JavaScript simples » (POJO) avec des propriétés exclusivement primitives, potentiellement imbriquées dans d'autres POJO ou tableaux de POJO. Dans ce contexte, ce type est appelé « DbModel » et serait un objet adapté à la persistance dans Firestore. Pour plus de commodité, les applications peuvent implémenter FirestoreDataConverter et enregistrer le convertisseur avec des objets Firestore, tels que DocumentReference ou Query , pour convertir automatiquement AppModel en DbModel lors du stockage dans Firestore, et convertir DbModel en AppModel lors de la récupération depuis Firestore.

Signature:

export declare interface FirestoreDataConverter<AppModelType, DbModelType extends DocumentData = DocumentData> 

Méthodes

Méthode Description
fromFirestore (instantané, options) Appelé par le SDK Firestore pour convertir les données Firestore en un objet de type AppModelType . Vous pouvez accéder à vos données en appelant : snapshot.data(options) . Généralement, les données renvoyées par snapshot.data() peuvent être converties en DbModelType ; cependant, cela n'est pas garanti car Firestore n'applique pas de schéma sur la base de données. Par exemple, les écritures à partir d'une version précédente de l'application ou les écritures à partir d'un autre client qui n'utilisait pas de convertisseur de type pourraient avoir écrit des données avec des propriétés et/ou des types de propriétés différents. L’implémentation devra choisir si elle souhaite récupérer progressivement les données non conformes ou générer une erreur. Pour remplacer cette méthode, voir .
toFirestore (objetmodèle) Appelé par le SDK Firestore pour convertir un objet de modèle personnalisé de type AppModelType en un objet JavaScript simple (adapté à l'écriture directe dans la base de données Firestore) de type DbModelType . Pour utiliser set() avec merge et mergeFields , toFirestore() doit être défini avec PartialWithFieldValue<AppModelType> . Le type WithFieldValue<T> étend T pour permettre également à FieldValues ​​telles que deleteField() d'être utilisées comme valeurs de propriété.
toFirestore (objetmodèle, options) Appelé par le SDK Firestore pour convertir un objet de modèle personnalisé de type AppModelType en un objet JavaScript simple (adapté à l'écriture directe dans la base de données Firestore) de type DbModelType . Utilisé avec setDoc() , et avec merge:true ou mergeFields . Le type PartialWithFieldValue<T> étend Partial<T> pour permettre à FieldValues ​​telles que arrayUnion() d'être utilisées comme valeurs de propriété. Il prend également en charge Partial imbriqués en permettant l'omission des champs imbriqués.

FirestoreDataConverter.fromFirestore()

Appelé par le SDK Firestore pour convertir les données Firestore en un objet de type AppModelType . Vous pouvez accéder à vos données en appelant : snapshot.data(options) .

Généralement, les données renvoyées par snapshot.data() peuvent être converties en DbModelType ; cependant, cela n'est pas garanti car Firestore n'applique pas de schéma sur la base de données. Par exemple, les écritures à partir d'une version précédente de l'application ou les écritures à partir d'un autre client qui n'utilisait pas de convertisseur de type pourraient avoir écrit des données avec des propriétés et/ou des types de propriétés différents. L’implémentation devra choisir si elle souhaite récupérer progressivement les données non conformes ou générer une erreur.

Pour remplacer cette méthode, voir .

Signature:

fromFirestore(snapshot: QueryDocumentSnapshot<DocumentData, DocumentData>, options?: SnapshotOptions): AppModelType;

Paramètres

Paramètre Taper Description
instantané RequêteDocumentSnapshot < DocumentDonnées , DocumentData > Un QueryDocumentSnapshot contenant vos données et métadonnées.
choix Options d'instantané Les SnapshotOptions de l'appel initial à data() .

Retour:

Type de modèle d'application

FirestoreDataConverter.toFirestore()

Appelé par le SDK Firestore pour convertir un objet de modèle personnalisé de type AppModelType en un objet JavaScript simple (adapté à l'écriture directe dans la base de données Firestore) de type DbModelType . Pour utiliser set() avec merge et mergeFields , toFirestore() doit être défini avec PartialWithFieldValue<AppModelType> .

Le type WithFieldValue<T> étend T pour permettre également à des FieldValues ​​telles que deleteField() d'être utilisées comme valeurs de propriété.

Signature:

toFirestore(modelObject: WithFieldValue<AppModelType>): WithFieldValue<DbModelType>;

Paramètres

Paramètre Taper Description
modèleObjet AvecFieldValue <AppModelType>

Retour:

AvecFieldValue <Type de modèle de base de données>

FirestoreDataConverter.toFirestore()

Appelé par le SDK Firestore pour convertir un objet de modèle personnalisé de type AppModelType en un objet JavaScript simple (adapté à l'écriture directe dans la base de données Firestore) de type DbModelType . Utilisé avec setDoc() , et avec merge:true ou mergeFields .

Le type PartialWithFieldValue<T> étend Partial<T> pour permettre à FieldValues ​​telles que arrayUnion() d'être utilisées comme valeurs de propriété. Il prend également en charge Partial imbriqués en permettant l'omission des champs imbriqués.

Signature:

toFirestore(modelObject: PartialWithFieldValue<AppModelType>, options: SetOptions): PartialWithFieldValue<DbModelType>;

Paramètres

Paramètre Taper Description
modèleObjet PartialWithFieldValue <AppModelType>
choix Définir les options

Retour:

PartialWithFieldValue <Type de modèle de base de données>

Exemple

Exemple simple

const numberConverter = {
    toFirestore(value: WithFieldValue<number>) {
        return { value };
    },
    fromFirestore(snapshot: QueryDocumentSnapshot, options: SnapshotOptions) {
        return snapshot.data(options).value as number;
    }
};

async function simpleDemo(db: Firestore): Promise<void> {
    const documentRef = doc(db, 'values/value123').withConverter(numberConverter);

    // converters are used with `setDoc`, `addDoc`, and `getDoc`
    await setDoc(documentRef, 42);
    const snapshot1 = await getDoc(documentRef);
    assertEqual(snapshot1.data(), 42);

    // converters are not used when writing data with `updateDoc`
    await updateDoc(documentRef, { value: 999 });
    const snapshot2 = await getDoc(documentRef);
    assertEqual(snapshot2.data(), 999);
}

Exemple avancé

// The Post class is a model that is used by our application.
// This class may have properties and methods that are specific
// to our application execution, which do not need to be persisted
// to Firestore.
class Post {
    constructor(
        readonly title: string,
        readonly author: string,
        readonly lastUpdatedMillis: number
    ) {}
    toString(): string {
        return `${this.title} by ${this.author}`;
    }
}

// The PostDbModel represents how we want our posts to be stored
// in Firestore. This DbModel has different properties (`ttl`,
// `aut`, and `lut`) from the Post class we use in our application.
interface PostDbModel {
    ttl: string;
    aut: { firstName: string; lastName: string };
    lut: Timestamp;
}

// The `PostConverter` implements `FirestoreDataConverter` and specifies
// how the Firestore SDK can convert `Post` objects to `PostDbModel`
// objects and vice versa.
class PostConverter implements FirestoreDataConverter<Post, PostDbModel> {
    toFirestore(post: WithFieldValue<Post>): WithFieldValue<PostDbModel> {
        return {
            ttl: post.title,
            aut: this._autFromAuthor(post.author),
            lut: this._lutFromLastUpdatedMillis(post.lastUpdatedMillis)
        };
    }

    fromFirestore(snapshot: QueryDocumentSnapshot, options: SnapshotOptions): Post {
        const data = snapshot.data(options) as PostDbModel;
        const author = `${data.aut.firstName} ${data.aut.lastName}`;
        return new Post(data.ttl, author, data.lut.toMillis());
    }

    _autFromAuthor(
        author: string | FieldValue
    ): { firstName: string; lastName: string } | FieldValue {
        if (typeof author !== 'string') {
            // `author` is a FieldValue, so just return it.
            return author;
        }
        const [firstName, lastName] = author.split(' ');
        return {firstName, lastName};
    }

    _lutFromLastUpdatedMillis(
        lastUpdatedMillis: number | FieldValue
    ): Timestamp | FieldValue {
        if (typeof lastUpdatedMillis !== 'number') {
            // `lastUpdatedMillis` must be a FieldValue, so just return it.
            return lastUpdatedMillis;
        }
        return Timestamp.fromMillis(lastUpdatedMillis);
    }
}

async function advancedDemo(db: Firestore): Promise<void> {
    // Create a `DocumentReference` with a `FirestoreDataConverter`.
    const documentRef = doc(db, 'posts/post123').withConverter(new PostConverter());

    // The `data` argument specified to `setDoc()` is type checked by the
    // TypeScript compiler to be compatible with `Post`. Since the `data`
    // argument is typed as `WithFieldValue<Post>` rather than just `Post`,
    // this allows properties of the `data` argument to also be special
    // Firestore values that perform server-side mutations, such as
    // `arrayRemove()`, `deleteField()`, and `serverTimestamp()`.
    await setDoc(documentRef, {
        title: 'My Life',
        author: 'Foo Bar',
        lastUpdatedMillis: serverTimestamp()
    });

    // The TypeScript compiler will fail to compile if the `data` argument to
    // `setDoc()` is _not_ compatible with `WithFieldValue<Post>`. This
    // type checking prevents the caller from specifying objects with incorrect
    // properties or property values.
    // @ts-expect-error "Argument of type { ttl: string; } is not assignable
    // to parameter of type WithFieldValue<Post>"
    await setDoc(documentRef, { ttl: 'The Title' });

    // When retrieving a document with `getDoc()` the `DocumentSnapshot`
    // object's `data()` method returns a `Post`, rather than a generic object,
    // which would have been returned if the `DocumentReference` did _not_ have a
    // `FirestoreDataConverter` attached to it.
    const snapshot1: DocumentSnapshot<Post> = await getDoc(documentRef);
    const post1: Post = snapshot1.data()!;
    if (post1) {
        assertEqual(post1.title, 'My Life');
        assertEqual(post1.author, 'Foo Bar');
    }

    // The `data` argument specified to `updateDoc()` is type checked by the
    // TypeScript compiler to be compatible with `PostDbModel`. Note that
    // unlike `setDoc()`, whose `data` argument must be compatible with `Post`,
    // the `data` argument to `updateDoc()` must be compatible with
    // `PostDbModel`. Similar to `setDoc()`, since the `data` argument is typed
    // as `WithFieldValue<PostDbModel>` rather than just `PostDbModel`, this
    // allows properties of the `data` argument to also be those special
    // Firestore values, like `arrayRemove()`, `deleteField()`, and
    // `serverTimestamp()`.
    await updateDoc(documentRef, {
        'aut.firstName': 'NewFirstName',
        lut: serverTimestamp()
    });

    // The TypeScript compiler will fail to compile if the `data` argument to
    // `updateDoc()` is _not_ compatible with `WithFieldValue<PostDbModel>`.
    // This type checking prevents the caller from specifying objects with
    // incorrect properties or property values.
    // @ts-expect-error "Argument of type { title: string; } is not assignable
    // to parameter of type WithFieldValue<PostDbModel>"
    await updateDoc(documentRef, { title: 'New Title' });
    const snapshot2: DocumentSnapshot<Post> = await getDoc(documentRef);
    const post2: Post = snapshot2.data()!;
    if (post2) {
        assertEqual(post2.title, 'My Life');
        assertEqual(post2.author, 'NewFirstName Bar');
    }
}