Tips on implementing computed properties in Vue.js while using TypeScript

There is a significant amount of documentation on how to utilize Vue.js with JavaScript, but very little information on using TypeScript. The question arises: how do you create computed properties in a vue component when working with TypeScript?

According to the official example, computed should be an object containing functions that will be cached based on their dependent properties.

Take a look at this example I created:

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}`;
        },
    }
}

Here's the accompanying 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 doesn't display anything. Can someone provide guidance on how to properly define computed in this scenario?

Answer №1

If you want to declare computed properties, property accessors are the way to go. Check out Vue Class Component for more information. The getter will be activated as soon as input is entered.

Here's an 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>

Answer №2

Vue's declaration files have a circular nature which can create challenges for TypeScript in inferring types for certain methods. To overcome this, it may be necessary to specify the return type for methods like render and those used in computed properties.

import Vue, { VNode } from 'vue'

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

If you encounter issues with type inference or member completion, providing annotations for certain methods can help resolve them. Enabling the --noImplicitAny option can assist in identifying many of these unannotated methods.

More Information

Answer №3

Learn Vite Vue 3.2+ with 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>

Understanding the setData Mutation in Vuex 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 }
}

The function mentioned above utilizes the spread operator ... to update object fields based on the data passed to it.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Could you explain the significance of the ^ symbol preceding a software version number?

Considering updating a package in my application, specifically the "@types/react-router-dom" from version "4.3.1" to "5.0.0". However, I'm hesitant as it is a large project and I don't want to risk breaking anything. While reviewing the package. ...

The checkbox in element-plus does not revert to being unchecked if it was initially checked

Currently, I have a checkbox implemented using element-plus: <el-checkbox v-model="slotProps.action.check_control" :checked="slotProps.action.check_control" size="large" class="ml-4" :id="slotProps. ...

Activating Vue-Bootstrap components through an image click event in VueJS 2

Seeking to achieve: VueJS integration with Bootstrap for clickable cards I am currently working on a VueJS project where I want the cards to be clickable and reveal collapsible elements upon click. To accomplish this, I have implemented a button with the ...

What steps should I take to resolve the ChunkLoadError related to signalr?

Recently, I encountered an issue while running my nx site locally. It seems that any federated app using signalR is now throwing a ChunkLoadError. I attempted various solutions such as changing the version of signalR, reloading the page, clearing cache, a ...

How to determine the presence of 'document' in Typecsript and NextJS

Incorporating NextJS means some server-side code rendering, which I can manage. However, I'm facing a challenge when trying to check for set cookies. I attempted: !!document && !!document.cookie as well as document !== undefined && ...

Ways to activate v-input-file using a v-btn

I am trying to activate a hidden v-input-file by clicking on a v-btn. Although I have successfully achieved this with a regular input file, I would prefer to use v-input-file. Here is the code I have implemented so far, but it does not seem to be working ...

Integrating TypeScript into an established create-react-app project

Struggling to integrate TypeScript into an existing create-react-app? I've always added it at the beginning of a project using create-react-app my-app --scripts-version=react-scripts-ts, but that's not working this time. The only "solution" I co ...

Capture and store the current ionic toggle status in real-time to send to the database

I have a list of names from the database that I need to display. Each name should have a toggle button associated with it, and when toggled, the value should be posted back to the database. How can I achieve this functionality in an Ionic application while ...

extract keys and values from an array of objects

I would like assistance with removing any objects where the inspectionScheduleQuestionId is null using JS. How can we achieve this? Thank you. #data const data = [ { "id": 0, "inspectionScheduleQuestionId": 1, ...

What is the best way to include anime.js into my Vue application?

Hey there! I could use some guidance on how to successfully import anime.js into my Vue project using vue cli. Any suggestions or solutions would be greatly appreciated! import anime from 'animejs' Vue.use(anime); I've attempted the above ...

Error encountered while attempting to utilize 'load' in the fetch function of a layer

I've been exploring ways to implement some pre-update logic for a layer, and I believe the fetch method within the layer's props could be the key. Initially, my aim is to understand the default behavior before incorporating custom logic, but I&ap ...

What separates the act of declaring a generic function from explicitly declaring a type for that very same generic function?

Here are two instances demonstrating the use of a generic function: function myGenericFunction<TFunc extends Function>(target:TFunc): string { return target.toString(); } Based on this response, this represents a declaration for a generic funct ...

Comparison of Vue router and Express backend

Hello! I'm a newcomer to the world of web development and I'm curious about the distinctions between using Vue Router and Express. As I work on creating a basic web application, I'm debating whether or not incorporating Express is essential ...

Exploring Next JS: Effectively altering SVG attributes and incorporating new elements

I have integrated SVGR to load an SVG as a component in my latest Next.js 13 application: import CvSvg from './../../public/image.svg' export default function Home() { return ( <div className="flex flex-col min-h-screen" ...

The name '__DEV__' is not discoverable at the moment

While working with the mobx library in my project, I encountered an issue after installing it using npm. Upon exploring the mobx/src/error.ts file within the node_modules folder, I came across a compile time error on line 78: const errors: typeof niceError ...

When utilizing the Angular 2 Stack, the Typescript Reflect.getMetadata('design:type'...) method may return an Object instead of a Date

When running the code sample below, it outputs "[Function: Date]", which is as expected. import 'reflect-metadata' function logType(target : any, key : string) { var t = Reflect.getMetadata("design:type", target, key); console.log(`${k ...

Modify the parental data upon the user's transition to a designated route

I am a beginner in VueJs, currently working on setting up a web application with Vue-route. My goal is to update the style of the <header> element when the user navigates to a specific URL, either directly through the "URL bar" or by using the "navig ...

Implementing experimental decorators and type reconciliation in TypeScript - A step-by-step guide

My basic component includes the following code snippet: import * as React from 'react'; import { withRouter, RouteComponentProps } from 'react-router-dom'; export interface Props { }; @withRouter export default class Movies extends R ...

Displaying Name Values in a <v-select> Component and Passing the Corresponding ID in the Axios POST Request in Vue.js

UPDATE: Issue resolved by including the return-object prop in v-select When a new student is added to the database using a vuetify form, I want to be able to assign them a course that exists within a list of available courses (also stored in the database) ...

How can I access the Vue instance in Vuepress2 in order to utilize external Vue plugins?

Trying to implement v-wave within VuePress 2 (the updated version powered by Vue 3). Followed the documentation and attempted to integrate v-wave as a local plugin in VuePress 2. .vuepress/config.js const vwave = require('path/to/v-wave.js'); ...