silk
silk

Reputation: 189

How do you infer types of props in the component of Vue 3?

How to get the value of props in the component of vue3 For the following components, I want to infer the types of props and data through the generic parameter passing of defineComponent, but the value of props cannot be obtained by doing so. How can I modify it?

import { defineComponent , Prop, Ref, toRefs} from 'vue'

interface MProps {
    day:  number
}

interface MData {
    day: Ref<number>,
}

export default defineComponent<MProps, MData>({

    setup(props, content) {
        const { day } = toRefs(props)
        console.log('props.day', props.day)

        return  {
            day: day,
        }
    },

    render() {
        return <div>
            {this.day}
        </div>
    }
})

Upvotes: 4

Views: 2899

Answers (1)

Yom T.
Yom T.

Reputation: 9180

You are using the first signature of defineComponent which expects a direct setup function. But the problem is, it doesn't extend ComponentOptionsBase for you to add a render function (such implementation is only available in the other overloads/signatures).

However, if you prefer, you could return a JSX element as a RenderFunction with the first signature; although sadly, as discussed on the comments down below—this is not working as expected (in that the props passed by the parent/consuming component actually get passed as DOM properties instead!). Hope we're not missing something very obvious here, like having to actually define the props somewhere?

export default defineComponent<MProps, MData>(function setup(props) {
  const { day } = toRefs(props);

  return () => (
    <div>{day}</div>
  );
})

If you are okay with using the second signature, however, the following approach (with Props Annotation) will give you the same effect of type inference at the expense of your structured contracts (interface).

import { defineComponent, PropType, toRefs } from 'vue';

type MonthNames = 'January' | 'February' | 'March';

interface ITodo {
  done: boolean;
  notes: string;
  dateCreated: Date;
  dateModified: Date;
}

export default defineComponent({
  props: {
    // We won't have issue with primitive values as they can be automatically inferred
    day: Number,

    // Here's our challenge. And `PropType` to the rescue!
    monthNames: Array as PropType<MonthNames>,

    todo: Object as PropType<ITodo>,

    todoList: Array as PropType<ITodo[]>,

    // Another variation: With custom class 
    todoList2: class TodoList implements Array<ITodo> {

    }
  },

  setup(props) {
    const { day, monthNames, todo, todoList } = toRefs(props);

    // If you use VSCode, you should get intellisense with the list of month names 
    // as soon as you type an opening quote
    monthNames.value = 'January';

    todo.value.done = true;

    todoList.value.push({
      done: false
    });

    return {}
  }
});

Upvotes: 4

Related Questions