Really hitting my head against a wall on this one. I remember working in Angular that TS interfaces can be used to type hint parameters.
I'd like to do the same for props in Vue.
Any ideas? Code is as follows but the check is only made against a standard Object so passing in ANY object is valid:
import Vue from 'vue';
import Person from './../models/Person';
export default Vue.extend({
name: 'HelloWorld',
props: {
person: {
type: Object as () => Person
},
},
});
Interface as follows:
export default interface Person {
firstName: string;
lastName: string;
}
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 also be familiar with Vue, vue-loader, and webpack. Vue 2 already has good support for TypeScript, and the recently published Vue 2.7 backported a lot of useful features from Vue 3, like composition API, <script setup> , and defineComponent , further improving the developer experience of TypeScript in Vue.
To let Typescript enters into your Vue components, 2 additions are mandatory in each component file: Adding the lang="ts" attribute to the script tag so that Typescript can recognized it.
Function modeThe URL /search?q=vue would pass {query: 'vue'} as props to the SearchUser component. Try to keep the props function stateless, as it's only evaluated on route changes. Use a wrapper component if you need state to define the props, that way vue can react to state changes.
Yep - so turns out you can't use interfaces. Makes total sense in hindsight when you consider things like type-hinting in PHP7.
The answer is to apply the interface to a class and the type hint using that class instead. With abstraction layers, my worries about having to apply the wrong class to a type hint were unfounded as any class extending or implementing the Person
class will be a valid value to pass to the person
prop.
export default interface NameInterface {
firstName: string;
lastName: string;
}
import NameInterface from './../interfaces/NameInterface';
export default class Person implements NameInterface {
firstName: string;
lastName: string;
constructor( firstName: string, lastName: string ) {
this.firstName = firstName;
this.lastName = lastName;
}
}
<script lang="ts">
import Vue from 'vue';
import Person from './../models/Person';
export default Vue.extend({
name: 'HelloWorld',
props: {
person: {
type: Person
},
},
});
</script>
If you're using classes instead of Vue.extend
you can use the @Prop()
decorator (from vue-property-decorator
) to have interfaces as type parameters.
With OP's interface:
export default interface Person {
firstName: string;
lastName: string;
}
The class declaration would become:
import {Component, Prop, Vue} from 'vue-property-decorator';
import Person from './../models/Person';
@Component
export default class HelloWorld extends vue {
@Prop() person : Person;
}
(Source on GitHub)
You could also use PropType<FooBar>
in place of Object as () => FooBar
(see the end of this medium article), but it has the same issues as OP mentioned.
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