Search code examples
javascripttypescriptoptional-chaining

Why am I getting "Object is possibly 'undefined'" in this optional chain?


I got here:

buyTicketData?.pricingOptions

this error:

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

Why it matters if left side of ? is undefined, ? wraps it, not?

here are the types:

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

This is the whole expression anyway

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

OK, find the solution:

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
}

I just do not know why this ugly ?? "" condition need.


Solution

  • If a is undefined, a.b throws exception while a?.b resolves to undefined. You still need to handle the undefined.

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

    resolves to

    buyTicketData?.pricingOptions?.[undefined]
    

    if startPaymentIn is undefined. This would throw error as undefined cannot be a key.

    A better way is to do a null check before everything if this variable is essential, so that you don't need ?. at all.

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