firebase 如何解决错误“TS2532:对象可能是“未定义的”?

b1zrtrql  于 2023-01-14  发布在  其他
关注(0)|答案(5)|浏览(140)

我尝试重新构建一个使用Firebase Cloud Functions和Firestore的Web应用示例。部署函数时,我收到以下错误:

src/index.ts:45:18 - error TS2532: Object is possibly 'undefined'.
45     const data = change.after.data();

这是一个函数:

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;
    }
  });

我只是试着部署这个函数来测试它。并且已经在网上搜索了类似的问题,但是没有找到任何其他的帖子来匹配我的问题。

z6psavjg

z6psavjg1#

随着TypeScript 3.7的发布,可选的链接(?运算符)现在正式可用。
因此,可以将表达式简化为以下形式:

const data = change?.after?.data();

您可以从该版本的release notes中了解更多,其中介绍了该版本发布的其他有趣特性。
运行以下命令以安装TypeScript的最新稳定版本。

npm install typescript

也就是说,在处理nullundefined值时,可选链接可以与零合并一起使用,以提供回退值

const data = change?.after?.data() ?? someOtherData();

补充要点:
如果在条件if语句中使用可选链接,则仍需要确保执行正确的值/类型相等检查。
以下操作在strict TypeScript中将失败,因为您可能将未定义的值与数字进行比较。

if (_?.childs?.length > 0)

相反,这是你应该做的:

if (_?.childs && _.childs.length > 0)
6rqinv9w

6rqinv9w2#

编辑/更新:

如果您使用的是Typescript 3.7或更高版本,现在还可以执行以下操作:

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 说changedata可能是undefined(取决于onUpdate返回什么)。
因此,您应该将其 Package 在null/undefined检查中:

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;
    }
}

如果你100%确定你的object总是被定义的,那么你可以把这个:

const data = change.after!.data();
iih3973s

iih3973s3#

对于其他面临类似问题的人,当你知道一个特定的对象属性不能为空时,你可以在有问题的项后面使用非空Assert操作符(!)。

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 = "";
    }
  }

由于不能在switch语句中定义dataToSend.naci,因此可以更新代码以包含感叹号,如下所示:

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 = "";
    }
  }
tzxcd3kk

tzxcd3kk4#

常量数据=在!.data()之后更改!.

xxhby3vn

xxhby3vn5#

解决问题的另一种方法:

const data = change!.after!.data();

但请注意,如果使用eslint,可能会出现错误:
禁止非空Assert。(eslint@typescript-eslint/no非空Assert)
您可以按如下方式禁用错误:

// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const data = change!.after!.data();

但我不建议这样做,最好更改eslint配置或按照documentation中的指示进行修复:

const data = change?.after?.data();

相关问题