Props typing in Vue.js 3 with TypeScript

15,380

Solution 1

You should use it with PropType imported from vue like Object as PropType<FlashInterface>:

import FlashInterface from '@/interfaces/FlashInterface';
import { ref,PropType, defineComponent } from 'vue';
import { useStore } from 'vuex';

export default defineComponent({
    props: {
        message: {
            type: Object as PropType<FlashInterface>,
            required: true
        }
    },
    setup(props) {
            // Stuff
        }
});

Note : you should create your component using defineComponent in order to get the types inference.

Solution 2

The compiler is complaining about missing a reference for a (custom) constructor during type checking (links to legacy docs but works the same way with the most recent version of Vue).

In Typescript, you might want to think of interfaces as a contract that an entity should conform to, so they aren't really a constructor, and therefore, we need to provide an implementation of those interfaces.

Since you are on Typescript, if you need to keep the interface, consider using the class equivalent:

// Name the constructor whatever you like,
// but I would personally prefix interfaces with an "I"
// to distinguish them with the constructors

class Flash implements FlashInterface {
  level: string;
  message: string;
  id?: string

  constructor() {
    // Be sure to initialize the values for non-nullable props
    this.level = '';
    this.message = '';
  }
}

export default {
  name: 'Home',

  props: {
    message: Flash
  }
}

An excerpt from the doc:

In addition, type can also be a custom constructor function and the assertion will be made with an instanceof check. For example, given the following constructor function exists:

props: {
  message: {
    type: function Person(firstName, lastName) {
      this.firstName = firstName
      this.lastName = lastName
    }
  }
}

And of course, another alternative would be as suggested in the other post with PropType. Either one will do. It's just a matter of preference, I guess.

Share:
15,380

Related videos on Youtube

chindit
Author by

chindit

Updated on June 04, 2022

Comments

  • chindit
    chindit almost 2 years

    I'm trying to type hint my props in a Vue 3 component, with composition API.

    So, I'm doing this:

    <script lang="ts">
    import FlashInterface from '@/interfaces/FlashInterface';
    import { ref } from 'vue';
    import { useStore } from 'vuex';
    
    export default {
        props: {
            message: {
                type: FlashInterface,
                required: true
            }
        },
        setup(props): Record<string, unknown> {
            // Stuff
        }
    };
    

    My FlashInterface looks like this:

    export default interface FlashInterface {
        level: string,
        message: string,
        id?: string
    }
    

    This interface works well except in this case where I got this error:

    ERROR in src/components/Flash.vue:20:10
    TS2693: 'FlashInterface' only refers to a type, but is being used as a value here.
        18 |    props: {
        19 |        message: {
      > 20 |            type: FlashInterface,
           |                  ^^^^^^^^^^^^^^
        21 |            required: true
        22 |        }
        23 |    },
    

    I don't understand why TypeScript thinks this is a value.

    What am I missing?

  • Farhod Nematov
    Farhod Nematov over 2 years
    What about if props type is array? It will be Array as PropType<FlashInterface> or Object as PropType<FleshInterface[]> ??
  • Boussadjra Brahim
    Boussadjra Brahim over 2 years
    @FarhodNematov it should be type: Array as PropType<FlashInterface[]>, or type: Array as PropType<Array<FlashInterface>>,
  • Farhod Nematov
    Farhod Nematov over 2 years
    Thank you. But I have problem. In my script setup part I have a props with type array. In a script setup body I want to manipulate property. so props = defineProps(messages: { type: Array as PropType<...> }); Then I want to get computed property. const a = props.messages.find(m => Here m have to be FlashInterface but idea can't know); idea can't know messages is array. I can't give me suggestions. How can I fix this issue?