pegido
pegido

Reputation: 699

How to type a computed property in the new composition API?

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

Answers (3)

Axel
Axel

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

Gass
Gass

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.

enter image description here

So, we don't need to explicitly write the type of most ref() constants. TypeScript will protect as anyways. Look at the following error:

enter image description here

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

acme
acme

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

Related Questions