Jamie Curnow
2 min readJun 14, 2021

--

Hi louis030195, I don’t know a good way of doing this. What I usually do is right at the top of the function, if it’s a create event, define what the data is using as :

exports.foo = functions.firestore
.document('coll/{docId}')
.onCreate(async (snap, context) => {
const something = snap.data() as YourType
// rest of code
})

And if it’s a changey event like onWrite or onUpdate, I use a little helper function:

import { getDataFromChange } from './somewhere/getDataFromChange'
exports.foo = functions.firestore
.document('coll/{docId}')
.onUpdate(async (change, context) => {
const { isCreate, isDelete, isUpdate, beforeData, afterData } = getDataFromChange<YourType>(change)
// rest of code
})

This getDataFromChangefunction could probs be better…:

// getDataFromChange.ts
import { DocumentSnapshot } from 'firebase-functions/lib/providers/firestore'
import { Change } from 'firebase-functions'
interface ChangeData<T> {
isDelete: boolean
isCreate: boolean
isUpdate: boolean
beforeData: T | null
afterData: T | null
}
interface ChangeDataCreate<T> extends ChangeData<T> {
isDelete: false
isCreate: true
isUpdate: false
beforeData: null
afterData: T
}
interface ChangeDataDelete<T> extends ChangeData<T> {
isDelete: true
isCreate: false
isUpdate: false
beforeData: T
afterData: null
}
interface ChangeDataUpdate<T> extends ChangeData<T> {
isDelete: false
isCreate: false
isUpdate: true
beforeData: T
afterData: T
}
export const getDataFromChange = <T = FirebaseFirestore.DocumentData>(change: Change<DocumentSnapshot>) => {
const { before, after } = change
if (!before.exists) {
// Create
const val: ChangeDataCreate<T> = {
isDelete: false,
isCreate: true,
isUpdate: false,
beforeData: null,
afterData: after.data() as T
}
return val
} else if (!after.exists) {
// Delete
const val: ChangeDataDelete<T> = {
isDelete: true,
isCreate: false,
isUpdate: false,
beforeData: before.data() as T,
afterData: null
}
return val
} else {
// Update
const val: ChangeDataUpdate<T> = {
isDelete: false,
isCreate: false,
isUpdate: true,
beforeData: before.data() as T,
afterData: after.data() as T
}
return val
}
}

Hope that helps! :)

--

--

Jamie Curnow
Jamie Curnow

Written by Jamie Curnow

I am a javascript developer living in beautiful Cornwall, UK. Ever curious, always learning.

No responses yet