skip to Main Content

I am creating a trigger function using Firebase Cloud Functions in TypeScript, and would like to assign the type of the data held in the snapshot directly in the onCreate function as such:

import { firestore } from "firebase-functions/v1"
import { QueryDocumentSnapshot } from "firebase-functions/v1/firestore";

interface PaymentDocumentInterface {
    amount: number;
    benefactorDetails: {
        email: string;
        marketingConsent: boolean;
    };
}

exports.updateDonationProjectAggregations = firestore.document('protectedEnvironmentData/financialData/payments/{paymentId}').onCreate(async (snapshot: QueryDocumentSnapshot<PaymentDocumentInterface>, context) => {
    console.log(`Processing payment with value: ${snapshot.data().amount}`);
});

When I attempt to do so, TS complains, saying:

Type ‘QueryDocumentSnapshot’ is not generic

Is there another way to assign the correct return type to the snapshot’s data() method, before the main code block?

I am not interested in declaring a new data variable and casting it with the appropriate type.

2

Answers


  1. Try with that import instead which is generic

    import { QueryDocumentSnapshot } from 'firebase-admin/firestore';
    
    Login or Signup to reply.
  2. As stated by your error, the functions.firestore.QueryDocumentSnapshot of the event handler is defined as QueryDocumentSnapshot<DocumentData>. In regular Firestore SDK use, you change DocumentData to something else using the query’s withConverter(converter) method before executing it.

    If you want to change DocumentData to a different type you have two options:

    Option 1: Feed it through a FirestoreDataConverter.

    import * as firestore from "firebase-admin/firestore";
    
    interface PaymentDocumentInterface {
      /* ... */
    }
    
    const paymentDocumentConverter: firestore.FirestoreDataConverter<PaymentDocumentInterface> = {
      toFirestore(post: PaymentDocumentInterface): firestore.DocumentData {
        return { /* ... */ };
      },
      fromFirestore(
        snapshot: firestore.QueryDocumentSnapshot,
        options: firestore.SnapshotOptions
      ): PaymentDocumentInterface {
        const data = snapshot.data(options)!;
        return {
          amount: data.amount,
          benefactorDetails: {
            email: data.benefactorDetails.email;
            marketingConsent: data.benefactorDetails.marketingConsent;
          }
        };
      }
    };
    
    export const updateDonationProjectAggregations = firestore.document('protectedEnvironmentData/financialData/payments/{paymentId}').onCreate(async (snapshot, context) => { // let this line type itself
        // data will be typed as PaymentDocumentInterface
        const data = paymentDocumentConverter.fromFirestore(snapshot, { serverTimestamps: 'none' });
    });
    

    Option 2: Manually cast it (not recommended, but fine for basic interfaces).

    export const updateDonationProjectAggregations = firestore.document('protectedEnvironmentData/financialData/payments/{paymentId}').onCreate(async (rawSnapshot, context) => { // let this line type itself
        const snapshot = rawSnapshot as unknown as QueryDocumentSnapshot<PaymentDocumentInterface>;
        const data = snapshot.data();
    });
    

    OR

    export const updateDonationProjectAggregations = firestore.document('protectedEnvironmentData/financialData/payments/{paymentId}').onCreate(async (rawSnapshot, context) => { // let this line type itself
        const data = rawSnapshot.data() as unknown as PaymentDocumentInterface;
    });
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search