ChatGPT解决这个技术问题 Extra ChatGPT

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

我正在尝试重建一个使用 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;
    }
  });

我只是试图部署该功能来测试它。并且已经在网上搜索了类似的问题,但找不到与我的问题匹配的任何其他帖子。


w
wentjun

随着 TypeScript 3.7 的发布,可选链(? 运算符)现在正式可用。

因此,您可以将表达式简化为以下内容:

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

您可以从该版本的 release notes 中了解更多信息,其中涵盖了该版本发布的其他有趣功能。

运行以下命令来安装最新的稳定版 TypeScript。

npm install typescript

话虽如此,在处理 nullundefined 值时,Optional Chaining 可以与 Nullish Coalescing 一起使用以提供备用值

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

附加点:

如果您在条件 if 语句中使用可选链接,您仍然需要确保您正在执行正确的值/类型相等性检查。

以下将在严格的 TypeScript 中失败,因为您可能正在将未定义的值与数字进行比较。

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

相反,这是你应该做的:

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

即使使用可选链接,对象上的数组也存在问题。
不幸的是,很难在注释中格式化代码,但它就在这里......我必须提供未定义的检查,因为它会抛出“对象可能未定义”: if (listingData && listingData.images) { image = listingData?.images[0 ]?.imageUrl; }
我在想,这里是 images 可选字段吗?这就是为什么它可能是undefined?在这种情况下,你想试试这个吗? if (listingData?.images) { image = listingData?.images?.[0].imageUrl; }
即使使用可选链接我仍然有错误 if (_?.childs?.length > 0)
有没有办法禁用该检查?我认为它在打字稿中根本没有用。更新:只需将 "strictNullChecks": false, 添加到 tsconfig.json 文件。
d
distante

编辑/更新:

如果您使用的是 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;
    }

原始回复

打字稿说 changedata 可能是 undefined (取决于 onUpdate 返回的内容)。

所以你应该把它包装在一个空/未定义的检查中:

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

如果我这样做,我会收到以下错误:error TS7030: Not all code paths return a value. 44 .onUpdate((change, context) =>
当第一个 if 语句返回 false 时,您现在需要返回一些内容。
哦,由于某种原因,我认为错误与更改和上下文对象有关。 #ashhamed 现在它可以工作了,但是我的代码看起来很糟糕,因为我还必须为 data 对象添加一个 if 查询,并且只是在 else 分支中添加了 return null;。有没有更清洁的方法来实现它? #HugeDougFan
使用 const data = change!.after!.data() 我得到一个错误,但使用 const data = change.after!.data() 它可以工作。十分感谢。 :)
好的,我也会修复它的答案。
S
Shiraz

对于面临与我类似的问题的其他人,您知道特定对象属性不能为空,您可以在相关项目之后使用非空断言运算符 (!)。这是我的代码:

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

关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅