'Props typing in Vue.js 3 with TypeScript
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?
Solution 1:[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.
script setup
You could define the props using defineProps
function in two ways :
<script setup lang="ts">
import FlashInterface from '@/interfaces/FlashInterface';
mport { ref,PropType, defineComponent , defineProps} from 'vue';
interface IProps{
message : FlashInterface
}
const props = defineProps<IProps>()
or
<script setup lang="ts">
...
const props = defineProps({
message: {
type: Object as PropType<FlashInterface>,
required: true
}
})
Solution 2:[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 aninstanceof
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.
Solution 3:[3]
You can use setup script to define your props
<script setup lang="ts">
import FlashInterface from '@/interfaces/FlashInterface';
import { ref } from 'vue';
import { useStore } from 'vuex';
interface Props{
message:FlashInterface
}
const {message} = defineProps<Props>()
for more information: Vue doc
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | |
Solution 3 | Farid |