mlvrkhn
mlvrkhn

Reputation: 95

Property 'index' does not exist on type 'my_variable' (Vue2, Typescript)

I have a variable called order which represents restaurant order (id, created_at, sum_vat, etc.).

In my code I want to loop over that object and display data in my template. The thing is that my order in OrderState is declared as undefined | Order as order might not exist before async code is fetches it.

Because of that, I need to set return type of my Computed property called order to undefined | Order. When I do that, in my template in the loop Typescript starts to complain that order might be undefined, and it is right about it.

So, to tell TypeScript that the value will be there, I just add ? to order, like so:

<li v-for="(l, index) in order?.order_lines" :key="index"> // Property 'index' does not exist on type 'order'.
  {{ index + 1 }}. {{ l.product.product_name }}
</li>

My question is: why is this the case and how do I tackle this issue? I'd just like to add that I do not care that much about how the types are declared, as long as they are correct and working in predictable way, so I am open for suggestions.

in my orders.types.ts

export type Order = {
  created_at: string
  current_status: number
  id: number
  info: OrderInfo
  method: number
  order_lines: OrderLine[]
  order_sum: number
  order_vat: number
  provider: Provider
}

export type OrderState = {
  order: undefined | Order
  ordersList: Array<Order>
}

export interface OrderStateMap {
  orders: OrderState
}

in my component:

<template>
  <div class="wrapper">
    <ul class="card-desc">
       <li v-for="(l, index) in order.order_lines" :key="index"> // here
       {{ index + 1 }}. {{ l.product.product_name }}
       </li>
    </ul>
  </div>
</template>

<script lang="ts">
import { Vue, Component } from 'vue-property-decorator'
import OrderService from '~/services/OrderServiceAPI'
import { setOrderDataInState } from '~/helpers/orders.state.helpers'
import { OrderStateMap, Order } from '~/types/store/orders.types'

@Component
export default class order extends Vue {
  /* Props */
  /* State */
  ordersState = (this.$store.state as OrderStateMap).orders
  /* Data */

  /* Hooks */
  created(): void {
    // this.handleOrderDataAsync()
  }

  /* Methods */
  async handleOrderDataAsync() {
    try {
      const { data } = await OrderService.getOrderData(
        this.$axios,
        this.orderId
      )
      setOrderDataInState(this.$store, data)
    } catch (err) {
      console.error('Error fetching order details. ', err.message)
    }
  }

  /* Computed */
  get order(): undefined | Order {
    return this.ordersState.order
  }

  get orderId(): number {
    return parseInt(this.$route.params.order)
  }
  /* Watchers */
}
</script>

Upvotes: 0

Views: 482

Answers (1)

ZloiGoroh
ZloiGoroh

Reputation: 443

Do not use question mark in template to get value of the object, use a computed getter instead

computed: {
    orderLines() {
        return this.order?.order_lines || []
    }
}

Upvotes: 1

Related Questions