Reputation: 699
I'm playing along with the new Vue.js plugin for using composition API and TypeScript and there is something I'm not understanding.
How am I supposed to type computed properties?
import Vue from 'vue'
import { ref, computed, Ref } from '@vue/composition-api'
export default Vue.extend({
setup(props, context) {
const movieName:Ref<string> = ref('Relatos Salvajes')
const country:Ref<string> = ref('Argentina')
const nameAndCountry = computed(() => `The movie name is ${movieName.value} from ${country.value}`);
return { movieName, country, nameAndCountry }
}
})
In this simple example I'm declaring two refs and a computed property to join both. VSC is telling me that computed properties are returning ReadOnly
type... But I can't make it work.
Upvotes: 43
Views: 57245
Reputation: 5141
I believe you should go with using generics:
const movieName = ref<string>("Relatos Salvajes")
const country = ref<string>("Argentina")
const nameAndCountry = computed<string>(
() => `The movie name is ${movieName.value} from ${country.value}`
)
https://vuejs.org/guide/typescript/composition-api.html#typing-computed
Upvotes: 7
Reputation: 9402
TypeScript in many cases will automatically infer the type. So let's say we have the following variable:
const movie = ref('relatos salvajes')
If you now move the mouse over movie
you'll see that TS infers that is a string
and if you try to change the value to for example a number it will throw an error.
So, we don't need to explicitly write the type of most ref()
constants. TypeScript will protect as anyways. Look at the following error:
Okay, now let's see something interesting. If you have a string
which you only want it to be two specific strings
, then we can use generics like so:
const movies = ref<'titanic'|'forest gump'>('titanic')
If we then try to set the value of movies to for example 'relatos salvajes'
TS will throw an error.
An example for numbers:
const movies = ref<0|10|20>(0)
Generics in computed properties
When using computed()
, types are also automatically infer, but if you would like to add specific interfaces or types then you can use generics the same way you would do it with ref()
interface User{
uid: string,
username: string,
age: number
}
const userData = computed<User>(() => store.state.user)
You can find more info here
Upvotes: 1
Reputation: 14856
There are two different types for that.
If your computed prop is readonly:
const nameAndCountry: ComputedRef<string> = computed((): string => `The movie name is ${movieName.value} from ${country.value}`);
if it has a setter method:
const nameAndCountry: WritableComputedRef<string> = computed({
get(): string {
return 'somestring'
},
set(newValue: string): void {
// set something
},
});
Upvotes: 69