What could be causing the "undefined object" warning within this optional chain?

I encountered this issue:

buyTicketData?.pricingOptions

resulting in this error message:

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

I'm puzzled as to why the left side of ? being undefined causes an error when it is wrapped with ?.

The types involved are as follows:

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 complete expression under consideration

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

Let's address this problem:

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

I am unsure why this somewhat messy ?? "" condition is necessary.

Answer №1

When a is not defined, attempting to access a.b will result in an exception, while a?.b will simply resolve to undefined. However, you still need to handle the case where it resolves to undefined.

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

will resolve as

buyTicketData?.pricingOptions?.[undefined]

if startPaymentIn is also undefined. This will throw an error because undefined cannot be used as a key.

A more robust approach would be to perform a null check before accessing any essential variables, eliminating the need for ?. altogether.

if(startPaymentIn)
{
    //No need for ?. when checking startPayment
}

Answer №2

You overlooked a single optional chaining operator for the potentially undefined invoiceItems. The correct way to perform the defaultValue lookup is as follows:

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

A helpful example demonstrating this issue can be found in the minimal reproducible example. Check it out on the 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
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Struggling with jquery's addClass method when trying to apply a class to

Below is a sample tr: <tr> <td><input type="text" class="ingredient required" name="ingredient"></td> <td><input type="number" class="amount required" name="amount" ></td> <td><input type="number" c ...

JavaScript code for downloading data through AJAX and then loading a chart is not functioning as expected

<script> var highchartsOptions = { chart: { backgroundColor: 'rgba(255, 255, 255, 0.1)', type: 'column' }, title: { text: '' }, exporting: ...

Determine whether something has the potential to be a string in TypeScript

I am looking to create a TypeScript type that can identify whether an element has the potential to be a string. This means the element should have the type "string" or "any", but not "number", "boolean", "number[]", "Person", etc. I have experimented wit ...

"The JavaScript code that functions perfectly in the browser console, but fails to execute when running in the actual

I'm encountering an issue with a simple piece of JavaScript code that seems to only work when executed in the browser console: <script> $(".hopscotch-close").click(function () { alert("Hi"); Cookies.set("tourState", "closed" ...

Retrieve items with identical ids, all in a single representation

I have an array filled with objects. My goal is to identify and return the objects with unique IDs, avoiding any duplicates. For example: let arr1 = [ {id: 1, name: 'A'}, {id: 3, name: 'C'}, {id: 1, name: 'A'}, {id: 2, name: ...

displayEvent not functioning properly within fullcalendar

I'm attempting to add an event to FullCalendar.io using a JavaScript function. I've tried two methods. Triggering the function at the end of the page or by clicking. No error is displayed, but the event isn't showing up on my calendar. & ...

Execute a PHP function using JavaScript/jQuery with AJAX requests

Hello everyone, I am reaching out for assistance with AJAX as I am still quite new to it. Despite the abundance of examples available, I find it challenging to grasp the concept. Specifically, I need help with my validation of a contact form using JavaScri ...

In Javascript, a variable is being defined by combining a string with another variable through concatenation

Hey, I'm relatively new to working with Javascript and am facing an issue that I believe can be resolved easily with the right syntax. The problem lies in setting a variable (totalRow1) where it needs to be concatenated with a string and another vari ...

How to efficiently update a nested array within the state of a React

Although the onChange function is working as expected, I am facing issues with updating the features in the state. Despite numerous attempts, I haven't been able to find examples similar to what I'm trying to achieve, so I decided to seek help. ...

Issues with Angular route links not functioning correctly when using an Array of objects

After hard coding some routerLinks into my application and witnessing smooth functionality, I decided to explore a different approach: View: <ul class="list navbar-nav"></ul> Ts.file public links = [ { name: "Home&quo ...

Adding a specified number to a value in React: x + y

I am facing an issue with adjusting the value of deliveryFee based on the changing value of a variable weight. Initially, I have set specific values for deliveryFee based on different weight ranges: Up to 2 kg => $3.40 Up to 5 kg => $3.80 Up to 10 k ...

Issue with Orgchart JS: The requested resource does not have the 'Access-Control-Allow-Origin' header present

Currently, I am developing a program to create organization charts using orgchart.js and simple PHP. This project does not involve any frameworks, but unfortunately, I encountered the following error: CORS policy is blocking access to XMLHttpRequest at & ...

The updateDoc function does not allow for using a variable as a field name

I am currently using the updateDoc function from Firestore and VueJs as my framework. I am attempting to create a nested document with the user input (member_name) as a field name. However, I am encountering an error stating "Unexpected keyword 'this& ...

Make sure to concentrate on the input field when the DIV element is clicked

In my React project, I am working on focusing on an input element when specific buttons or elements are clicked. It is important for me to be able to switch focus multiple times after rendering. For instance, if a name button is clicked, the input box for ...

A guide on organizing JSX elements based on JSON data

What I Aim to Achieve: I am looking to display a list of elements using the .map method, and then arrange them in descending order based on their date. Despite attempting to use .sort and .filter before rendering the elements, I have not been successful. ...

Guide on executing a jar file using JavaScript and obtaining a JSON output

Is there a way to execute and capture the output of a jar file that returns a json using javascript? ...

Utilize the UserService in NestJs to enhance security within the RolesGuard functionality

In my application, I have a module called UserModule that exports the UserService. Here is an example of how it is done: @Module({ imports: [ MongooseModule.forFeature([{ name: User.name, schema: UserSchema }]), MongooseModule.forFeature([{ name: ...

What is the best way to sequentially read various sections of a file in vue.js?

I am currently working on a browser tool that analyzes a large file and provides statistics based on its content. The tool randomly selects k parts of the file for processing, treating each part individually. As each part is processed, an object is update ...

Check if the value is a string and contains a floating point number; if so, parse and format the float

I need to work on formatting decimal values returned by an API that only responds with strings. The requirement is to add a leading zero but no trailing zeros to any decimal value in the string. If the value is not a float, it should remain unchanged. For ...

How can we effectively implement conditional rendering when dealing with components that are nearly identical?

Depending on whether the user is a professor, student, or not logged in, I render different landing pages. The landing pages are quite similar, with the only distinction being the buttons displayed. While I could easily achieve this using inline conditions ...