Prop is possibly undefined error in Vue 3 setup

Viewed 6617

The console.log('test',props.list) works well. But props.list.map doesn't work. Here is the error message.

enter image description here

And here is the code of the component How can I fix this error?

<template>
  <div class="row">
      <div v-for="column in columnList" :key="column.id" class="col-4 mb-4">
          <div class="card-body">
            <div class="card h-100 shadow-sm" >
                <img :src="column.avatar" :alt="column.title">
                <h5>{{column.title}}</h5>
                <p>{{column.description}}</p>
                <a href="#" class="btn btn-primary">enter</a>
            </div>
          </div>

      </div>
  </div>
</template>

<script lang='ts'>
import { computed, defineComponent, PropType } from 'vue'

export interface ColumnProps{
    id: number;
    title: string;
    avatar?: string;
    description: string;
}

export default defineComponent({
  name: 'ColumnList',
  props: {
    list: {
      type: Array as PropType<ColumnProps[]>,
      require: true
    }
  },
  setup (props) {
    const columnList = computed(() => {
      console.log('test',props.list)
      return props.list.map(column => {
        if (!column.avatar) {
          column.avatar = require('../assets/default_avatar.jpg')
        }
        return column
      })
    })
    return { columnList }
  }
})
</script>

4 Answers

I think, the only bit missing is a typo in the required option.

Change

props: {
    list: {
      type: Array as PropType<ColumnProps[]>,
      require: true
    }
  },

to

props: {
    list: {
      type: Array as PropType<ColumnProps[]>,
      required: true // <-----  CHANGE TO "required"
    }
  },

It's a typescript error (TS2532). The type of props is unknown. You need to specify a type for the props parameter, like this:

interface Props {
  list: ColumnProps[];
}

setup(props: Props) {
  ...
}

Your current props definitions only tell Vue what props and types to expect, but not Typescript

I'm guessing the list prop is populated by an async call. If so, the computed runs at least once before props.list is defined. When it's undefined, it has no .map method.

Provide for that situation by returning an empty array:

setup (props) {
  const columnList = computed(() => {
    if (!props.list) return [];         // ✅ Return an empty array if undefined
    return props.list.map(column => {
      if (!column.avatar) {
        column.avatar = require('../assets/default_avatar.jpg')
      }
      return column
    })
  })
  return { columnList }
}

Your error comes from typescript.

This is because of the way vue defines your props for typescript. If you had required: true, then you state it cannot not be undefined, else it may.

The accepted answer is conceptually wrong, but it works because the you check for undefined before accessing the value if (!props.list) ... and the compiler is smart enough to know that.

If you know it will be defined and do not want to use required: true, you can tell it the compiler by writing props.list!.map

Related