54

There is a lot of documentation how to interact with Vue.js using the JavaScript language and just a little about TypeScript. The question is how do you define computed props in a vue component if it is written in TypeScript?

According the official example, computed is an object with functions which will be cached based on their dependent props.

Here is an example I made:

import Vue from 'vue';
import { Component } from "vue-property-decorator";

@Component({})
export default class ComputedDemo extends Vue {
    private firstName: string = 'John';
    private lastName: string = 'Doe';
    private computed: object = {
        fullName(): string {
            return `${this.firstName} ${this.lastName}`;
        },
    }
}

And html:

<div>
    <h1>Computed props ts demo</h1>
    <ul>
        <li>First name: {{firstName}}</li>
        <li>Last name: {{lastName}}</li>
        <li>Together: {{fullName}}</li>
    </ul>
</div>

The third list item outputs nothing. Can anybody tell me how to define computed in this case, please?

0

3 Answers 3

80

You can use property accessors to declare computed properties. See Vue Class Component. The getter will be triggered as soon as you type in the input.

For example:

<template>
    <div>
        <input type="text" name="Test Value" id="" v-model="text">

        <label>{{label}}</label>
    </div>

</template>

<script lang="ts">
import { Component, Vue, Watch } from "vue-property-decorator";

@Component({})
export default class About extends Vue {
    private text = "test";

    get label() {
        return this.text;
    }
}
</script>

Update for Vue Composition Api

<template>
  <div>
    <input type="text" name="Test Value" id v-model="text" />

    <label>{{label}}</label>
  </div>
</template>

<script lang="ts">
import { defineComponent, ref, computed } from "@vue/composition-api";

export default defineComponent({
  setup() {
    const text = ref("test");

    const label = computed(() => {
      return text.value;
    });

    return {
      text,
      label
    };
  }
});
</script>
Sign up to request clarification or add additional context in comments.

3 Comments

It works and looks easy to use. And also Vue plugin in browser marks such getters as computed props.
Watch is never used on the 1st example, am I missing something?
no, it doesnt matter. he forgot to remove it.
23

Because of the circular nature of Vue’s declaration files, TypeScript may have difficulties inferring the types of certain methods. For this reason, you may need to annotate the return type on methods like render and those in computed.

import Vue, { VNode } from 'vue'

const Component = Vue.extend({
  data () {
    return {
      msg: 'Hello'
    }
  },
  methods: {
    // need annotation due to `this` in return type
    greet (): string {
      return this.msg + ' world'
    }
  },
  computed: {
    // need annotation
    greeting(): string {
      return this.greet() + '!'
    }
  },
  // `createElement` is inferred, but `render` needs return type
  render (createElement): VNode {
    return createElement('div', this.greeting)
  }
})

If you find type inference or member completion isn’t working, annotating certain methods may help address these problems. Using the --noImplicitAny option will help find many of these unannotated methods.

More Info

3 Comments

This works in my case and doesn't require rewriting to class-based component style.
So why we use typescript with this block of code? we can't set type to variables in the object that data function returns.
This fixed a problem I was having. Thanks!
4

Vite Vue 3.2+ TypeScript

<template>
    <input type="text" v-model="title" />
</template>

<script setup lang="ts">
import { computed } from 'vue';
import { useStore } from 'vuex';

const store = useStore()

const title = computed({
    get: () => store.state.page.about.title,
    set: value => store.commit('setData', { about: { title: value }})
})
</script>

Mutation setData in store

setData(state: { about: any, blog: any, contact: any, home: any }, data: any) {
     if (data['about']) state.about = { ...state.about, ...data.about }
     if (data['blog']) state.blog = { ...state.blog, ...data.blog }
     if (data['contact']) state.contact = { ...state.contact, ...data.contact }
     if (data['home']) state.home = { ...state.home, ...data.home }
}

Function above by using spread operator ... will overwrite object field you send to them.

1 Comment

The answer what I want !

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.