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 getDataFromChange
function 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 } = changeif (!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! :)