网站搜索

javascript - 为什么在这个可选链中我会收到“对象可能是‘undefined’”?


我到了这里:

buyTicketData?.pricingOptions

这个错误:

[tsl] ERROR in /Applications/MAMP/htdocs/wp-content/plugins/tikex/tikexModule/components/BuyTicket/PricingOptionInvoiceItemsFormFieldsCheckboxes.tsx(280,25)
      TS2532: Object is possibly 'undefined'.

如果 ? 的左侧是未定义的,为什么会重要,? 不是会包裹它吗?

类型如下:

buyTicketData?: BuyTicketData;

export type BuyTicketData = {
  pricingOptions?: PricingOptions;
}

export type PricingOptions = {
  [optionId: string]: PricingOptionType;
};

export type PricingOptionType = {
  invoiceItems?: InvoiceItems;
};

export type InvoiceItems = {
  [invoiceItemId: string]: InvoiceItemData;
};

export type InvoiceItemData = {
  defaultValue?: number;
};

无论如何,这就是整个表达

<select
value={
startPaymentIn?.invoiceItems?.[key] != undefined
  ? startPaymentIn?.invoiceItems?.[key] == 1
    ? "Igen"
    : "Nem"
  : startPaymentIn?.pricingOptionId &&
    buyTicketData?.pricingOptions?.[ // <-- here
      startPaymentIn!.pricingOptionId!
    ].invoiceItems[key]?.defaultValue != undefined
  ? startPaymentIn?.pricingOptionId &&
    buyTicketData?.pricingOptions?.[
      startPaymentIn!.pricingOptionId!
    ].invoiceItems[key]?.defaultValue == 1
    ? "Igen"
    : "Nem"
  : undefined
}

好的,找到解决方案:

value={
  startPaymentIn?.invoiceItems?.[key] != undefined
    ? startPaymentIn?.invoiceItems?.[key] == 1
      ? "Igen"
      : "Nem"
    : buyTicketData?.pricingOptions?.[
        startPaymentIn?.pricingOptionId ?? ""
      ]?.invoiceItems?.[key]?.defaultValue != undefined
    ? buyTicketData?.pricingOptions?.[
        startPaymentIn?.pricingOptionId ?? ""
      ]?.invoiceItems?.[key]?.defaultValue == 1
      ? "Igen"
      : "Nem"
    : undefined
}

我只是不明白为什么需要这个丑陋的 ?? "" 条件。

答案#1

如果 a 是 undefined,a.b 会抛出异常,而 a?.b 会解析为 undefined。你仍然需要处理 undefined。

buyTicketData?.pricingOptions?.[startPaymentIn?.pricingOptionId]

解析为

buyTicketData?.pricingOptions?.[undefined]

如果 startPaymentIn 是 undefined。这将抛出错误,因为 undefined 不能作为键。

如果这个变量是必需的,更好的方法是在所有操作之前进行空检查,这样你就完全不需要 ?. 了。

if(startPaymentIn)
{
    //no need to use ?. on startPayment
}

答案#2

你漏掉了一个可能未定义的 invoiceItems 的可选链操作符。defaultValue 的查找应该像这样:

buyTicketData?.pricingOptions?.[startPaymentIn!.pricingOptionId!]
    .invoiceItems?.[key]?.defaultValue

以下最小可复现示例说明了这一点。可以在 Playground 中尝试它以查看错误。

export type BuyTicketData = {
    pricingOptions?: PricingOptions;
}

export type PricingOptions = {
    [optionId: string]: PricingOptionType;
};

export type PricingOptionType = {
    invoiceItems?: InvoiceItems
}

export type InvoiceItems = {
    [invoiceItemId: string]: InvoiceItemData
}

export type InvoiceItemData = {
    defaultValue?: number
}

let startPaymentIn: PricingOptionType & { pricingOptionId?: string } = {}

function testContext (key: string, buyTicketData?: BuyTicketData) {

    // incrementally testing your expression until we isolate the actual error
    let w = buyTicketData?.pricingOptions
    let x = buyTicketData?.pricingOptions?.[startPaymentIn!.pricingOptionId!]
    let y = buyTicketData?.pricingOptions?.[startPaymentIn!.pricingOptionId!].invoiceItems
    let z = buyTicketData?.pricingOptions?.[startPaymentIn!.pricingOptionId!].invoiceItems[key]
    // ^^^ error on this last line
    
    // the correct expression to get the `defaultValue`
    const defaultValue =
        buyTicketData?.pricingOptions?.[startPaymentIn!.pricingOptionId!].invoiceItems?.[key]?.defaultValue

    return startPaymentIn?.invoiceItems?.[key] != undefined
        ? startPaymentIn?.invoiceItems?.[key] == 1
            ? "Igen"
            : "Nem"
        : startPaymentIn?.pricingOptionId &&
          buyTicketData?.pricingOptions?.[
              startPaymentIn!.pricingOptionId!
              ].invoiceItems?.[key]?.defaultValue != undefined
            ? startPaymentIn?.pricingOptionId &&
              buyTicketData?.pricingOptions?.[
                  startPaymentIn!.pricingOptionId!
                  ].invoiceItems?.[key]?.defaultValue == 1
                ? "Igen"
                : "Nem"
            : undefined
}