I'm trying to rebuild a web app example that uses Firebase Cloud Functions and Firestore. When deploying a function I get the following error:
src/index.ts:45:18 - error TS2532: Object is possibly 'undefined'.
45 const data = change.after.data();
This is the function:
export const archiveChat = functions.firestore
.document("chats/{chatId}")
.onUpdate(change => {
const data = change.after.data();
const maxLen = 100;
const msgLen = data.messages.length;
const charLen = JSON.stringify(data).length;
const batch = db.batch();
if (charLen >= 10000 || msgLen >= maxLen) {
// Always delete at least 1 message
const deleteCount = msgLen - maxLen <= 0 ? 1 : msgLen - maxLen
data.messages.splice(0, deleteCount);
const ref = db.collection("chats").doc(change.after.id);
batch.set(ref, data, { merge: true });
return batch.commit();
} else {
return null;
}
});
I'm just trying to deploy the function to test it. And already searched the web for similar problems, but couldn't find any other posts that match my problem.
This question is related to
typescript
firebase
google-cloud-firestore
google-cloud-functions
If you are using Typescript 3.7 or newer you can now also do:
const data = change?.after?.data();
if(!data) {
console.error('No data here!');
return null
}
const maxLen = 100;
const msgLen = data.messages.length;
const charLen = JSON.stringify(data).length;
const batch = db.batch();
if (charLen >= 10000 || msgLen >= maxLen) {
// Always delete at least 1 message
const deleteCount = msgLen - maxLen <= 0 ? 1 : msgLen - maxLen
data.messages.splice(0, deleteCount);
const ref = db.collection("chats").doc(change.after.id);
batch.set(ref, data, { merge: true });
return batch.commit();
} else {
return null;
}
Typescript is saying that change
or data
is possibly undefined
(depending on what onUpdate
returns).
So you should wrap it in a null/undefined check:
if(change && change.after && change.after.data){
const data = change.after.data();
const maxLen = 100;
const msgLen = data.messages.length;
const charLen = JSON.stringify(data).length;
const batch = db.batch();
if (charLen >= 10000 || msgLen >= maxLen) {
// Always delete at least 1 message
const deleteCount = msgLen - maxLen <= 0 ? 1 : msgLen - maxLen
data.messages.splice(0, deleteCount);
const ref = db.collection("chats").doc(change.after.id);
batch.set(ref, data, { merge: true });
return batch.commit();
} else {
return null;
}
}
If you are 100% sure that your object
is always defined then you can put this:
const data = change.after!.data();
For others facing a similar problem to mine, where you know a particular object property cannot be null, you can use the non-null assertion operator (!) after the item in question. This was my code:
const naciStatus = dataToSend.naci?.statusNACI;
if (typeof naciStatus != "undefined") {
switch (naciStatus) {
case "AP":
dataToSend.naci.certificateStatus = "FALSE";
break;
case "AS":
case "WR":
dataToSend.naci.certificateStatus = "TRUE";
break;
default:
dataToSend.naci.certificateStatus = "";
}
}
And because dataToSend.naci
cannot be undefined in the switch statement, the code can be updated to include exclamation marks as follows:
const naciStatus = dataToSend.naci?.statusNACI;
if (typeof naciStatus != "undefined") {
switch (naciStatus) {
case "AP":
dataToSend.naci!.certificateStatus = "FALSE";
break;
case "AS":
case "WR":
dataToSend.naci!.certificateStatus = "TRUE";
break;
default:
dataToSend.naci!.certificateStatus = "";
}
}
Source: Stackoverflow.com