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?
Vue is written in TypeScript itself and provides first-class TypeScript support. All official Vue packages come with bundled type declarations that should work out-of-the-box.
Now that Vue. js officially supports TypeScript, it's possible to create TypeScript projects from scratch using Vue CLI. However, you still need some third-party packages with custom decorators and features to create a true, complete TypeScript application.
To specify the type of prop you want to use in Vue, you will use an object instead of an array. You'll use the name of the property as the key of each property, and the type as the value. If the type of the data passed does not match the prop type, Vue sends an alert (in development mode) in the console with a warning.
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';
import { 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
}
})
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With