You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用可选链仍触发TypeError:无法读取undefined的data属性求助

你猜的完全没错!问题就出在索引访问的后面没有跟上可选链操作符。咱们一步步拆解为什么你用了?.还是会报错:

问题根源:可选链的作用范围有限

在你原代码的报错行error.graphQLErrors?.[0].data里:

  • ?.只负责检查error.graphQLErrors是否为null或undefined。如果graphQLErrors确实存在(比如是一个空数组[]),那么[0]会返回undefined。
  • 这时候你直接访问.data,就相当于在undefined上读取属性,自然会触发Cannot read property 'data' of undefined的错误——因为可选链的“保护”只到graphQLErrors这一步,后面的索引访问和属性访问并没有被覆盖。

关于variable?.[0]的疑问解答

variable?.[0]里的第一个?.是判断variable本身是否为null/undefined:

  • 如果variable不存在,直接返回undefined,不会执行索引操作;
  • 如果variable存在,才会执行[0]索引访问,但索引的结果可能还是undefined(比如数组为空)。

这时候如果要继续访问索引结果的属性,必须在[0]后面再加一个?.,也就是variable?.[0]?.data——第二个?.的作用就是检查索引0对应的结果是否为null/undefined,如果是的话就直接返回undefined,不会继续往下访问.data。

修正后的代码

把所有涉及graphQLErrors?.[0].data的地方,都补上索引后的可选链:

useEffect(() => {
  let message: string | undefined;
  const error = createError ?? updateError;
  if (error) {
    if (
      // @ts-ignore
      error.graphQLErrors?.[0]?.data?.messages?.[0] // 索引后添加?
    )
      // @ts-ignore
      message = error.graphQLErrors?.[0]?.data?.messages?.[0];
    if (error?.message.includes('same organization as the scenario'))
      message = 'To create a new scenario, all target areas must be in the same organization as that scenario. You can fix this in the data tab at the top.';
    // @ts-ignore
    if (typeof error?.graphQLErrors?.[0]?.data?.errors?.[1]?.data?.messages?.[0] === 'string')
      // @ts-ignore
      message = error?.graphQLErrors?.[0]?.data?.errors?.[1]?.data?.messages?.[0];
    if (!message) {
      message = `Something went wrong with the network request`;
      console.log(error.message);
    }
    addToast(message, 10000);
  }
}, [addToast, createError, updateError]);

额外建议:替代@ts-ignore的更优方案

长期来看,频繁使用@ts-ignore会弱化类型检查的作用,你可以扩展GraphQL Error的类型定义来适配后端返回的结构:

import { GraphQLFormattedError } from 'graphql';

interface GraphQLCustomError extends GraphQLFormattedError {
  data?: {
    messages?: string[];
    errors?: Array<{
      data?: {
        messages?: string[];
      };
    }>;
  };
}

之后把error.graphQLErrors断言为GraphQLCustomError[],就能去掉@ts-ignore,同时获得准确的类型提示。

内容的提问来源于stack exchange,提问作者Diesel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 07:37:57