Challenges of Vue 3 Typescript ComputedRef

I've run into some challenges with Typescript and Vue3. It seems like I might be using Typescript incorrectly in this case.

I set up a store using Vue's Composition API.

import {computed, reactive} from "vue";

const state = reactive({
    accessToken: undefined,
    user: {},
})

const isAuthenticated = computed(() => {
    return state.accessToken !== undefined
})

export default {
    state: readonly(state),
    isAuthenticated
}

I also created a type or interface for it:

import {ComputedRef} from "vue";

export interface UserStore{
    state: Readonly<any>;
    isAuthenticated: ComputedRef<boolean>;
}

However, when I try to use it in my Vue component,

such as in the following example:

<h1 v-if="userStore.isAuthenticated">is true</h1>

It returns true even when it should clearly be false.

I inject the store using the inject function:

setup(){
    return {
      userStore: inject('userStore') as UserStore
    }
  }

A similar issue arises when attempting to return a computed string. It gets wrapped in quotation marks when used in a template.

What could be causing this issue?

#edit I am providing the UserStore in main.ts

/* Stores */
import UserStore from './store/user-store'

const app = createApp(App)
  .use(IonicVue, {
    mode: 'ios'
  })
  .use(router)
.provide('userStore',UserStore);

router.isReady().then(() => {
  app.mount('#app');
});

Answer №1

When dealing with a ref in Vue, the userStore.isAuthenticated expression will always evaluate to true.

In templates, refs, including computed ones, get automatically unwrapped when returned from the setup function. It should look something like this:

const userStore = inject('userStore') as UserStore
const { isAuthenticated } = userStore;

return {
  isAuthenticated
}

If not done automatically, a ref can be manually unwrapped like so:

<h1 v-if="userStore.isAuthenticated.value">is true</h1>

Answer №2

If you wish to define a computed property in TypeScript, you must use the "get" keyword before the method.

get isAuthenticated () {
    return state.accessToken !== undefined
)

To create a type interface:

interface recordTypes {
    pDate: Date;
}

Below is a comprehensive example:

<template>
   
    <component
        v-if="componentName != ''"
        v-bind:is="componentName"
        v-on:updateConfirmationStatus="updateConfirmation"
    >
    </component>

   
</template>

<script lang="ts">
import { Vue, Options } from "vue-class-component";
import { useStore, ActionTypes } from "../store";
import Toaster from "../helpers/Toaster";
import { reactive } from "vue";
import PatientConsultationService from "../service/PatientConsultationService";
import Confirmation from "../components/Confirmation.vue";
import { required } from "@vuelidate/validators";
import useVuelidate from "@vuelidate/core";
import { camelCase } from "lodash";
import moment from "moment";

// Define interface for record types
interface recordTypes {
    pDate: Date;
}

@Options({
    components: {
        Confirmation
    }
})
export default class Assessments extends Vue {
    // Class properties
    private recordList: recordTypes[] = [];
    private recordID = 0;
    private pService;
    private isCollapsed = true;
    private submitted = false;
    private toast;
    private componentName = "";
    private vuexStore = useStore();

    // Reactive data
    private state = reactive({
        weight: 0,
        height: 0,
        o2: 0,
        respiration: 0,
        temperature: 0,
        pressure: 0,
        pulse: 0
    });

    // Validation rules
    private validationRules = {
        weight: {
            required
        },
        height: {
            required
        },
        o2: {
            required
        },
        respiration: {
            required
        },
        temperature: {
            required
        },
        pressure: {
            required
        },
        pulse: {
            required
        }
    };

    // Validations using Vuelidate
    private v$ = useVuelidate(this.validationRules, this.state);

    // Lifecycle methods
    created() {
        this.pService = new PatientConsultationService();
        this.toast = new Toaster();
    }

    mounted() {
        this.loadList();
    }

    // Computed property
    get patientID() {
        return this.vuexStore.getters.getReceiptID;
    }

    // Methods for saving and clearing items
    saveItem(isFormValid) {
        // Save item logic
    }

    clearItems() {
        // Clear items logic
    }

    // Method for loading list
    loadList() {
        // Load list logic
    }

    // Method for cameling keys
    camelizeKeys = obj => {
        // Camelize keys logic
    };

    // Computed property for sorting records
    get sortedRecords() {
        // Sort records logic
    }

     // Format date method
   formatDate(d) {
        // Format date logic
    }

    // Delete item method
    deleteItem(id) {
        // Delete item logic
    }

    // Update confirmation method
    updateConfirmation(b) {
        // Update confirmation logic
    }
}
</script>

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

Unlock the potential of Vue custom props within the asyncData function in your nuxtjs project!

I have a special function in my project that serves as a plugin import Vue from 'vue' function duplicateText(text) { var input = document.createElement('input'); input.setAttribute('value', text); document.body.a ...

The error message "Property 'then' is not available on type 'void' within Ionic 2" is displayed

When retrieving data from the Google API within the function of the details.ts file, I have set up a service as shown below. However, I am encountering a Typescript error stating Property 'then' does not exist on type 'void'. this.type ...

Using WebSockets in Angular 4

Currently in the process of developing a chat application using Angular 4 and WebSocket. I found guidance from this Angular WebSocket tutorial This is the source code for the WebsocketService: import { Injectable } from '@angular/core'; import ...

How to remove a loop-rendered component from the DOM in Vue

My website has an image upload form where users can select multiple images. Once the images are selected, they are previewed and users can provide meta info such as Category and Type for each image. This functionality is implemented in the upload.vue file ...

Error: Unexpected token '<' encountered in Vue causing SyntaxErrorParsed: the parser expected an expression but found '<' instead

While working on my Vue project in my local environment (running the npm run dev command), I encountered an issue. When the first page loads, there are no errors. However, upon hitting the refresh button, the console displays a "SyntaxError: expected expre ...

Unending redirections caused by Nuxt middleware

I've implemented a middleware that checks the user's registration step and redirects them to the appropriate page. Here is my code: export default function ({app, redirect, route}) { let auth = app.$auth; console.log('step checks mi ...

Having Difficulty Modifying the CSS Styles of a Specific Class

I've been struggling with a CSS styling issue for some time now. The problem lies in targeting the class for the thumbnail preview of vue2-dropzone (which shares similar properties with dropzone.js based on documentation). Each time I upload an image, ...

Observable dataset

I'm curious about the correct type of Observables array. Can you advise? So far, I've attempted the following: let myObservables: Observable[] = new Array(); let myObservables: Observable<Array<any>> = new Array(); let myObservables ...

What is the most effective method for locating and modifying the initial instance of an element within a group?

In my Javascript/Typescript collection, I have the following items: [ {"order":1,"step":"abc:","status":true}, {"order":2,"step":"xyz","status":true}, {"order":3,"step":"dec","status":false}, {"order":4,"step":"pqr","status":false}, {"order":5,"step":" ...

Unsteady movement of Three JS OrbitControls during rotation

Currently, I am working on a scene with three.js and using orbit controls to rotate the camera around the scene. Occasionally, while rotating, the camera starts moving erratically before calming down and rotating smoothly again. I have read about orbit co ...

How can you display a set of components in React using TypeScript?

I'm currently working on rendering an array of JSX Components. I've identified two possible methods to achieve this. Method one (current approach): Create the array as an object type that stores the component properties and then build the JSX co ...

position the tooltip within the ample available space of a container in an angular environment

In my editor, users can create a banner and freely drag elements within it. Each element has a tooltip that should appear on hover, positioned on the side of the element with the most space (top, left, bottom, right). The tooltip should never extend outsid ...

What steps should I take to make sure the vuex store is included in my build process?

I am currently working on a Vue application using vue cli 3. I found a guide here that explains how to build the app with vue-cli-service build --target wc --name my-element [entry] In order to test the output, I have created an index.html file: <!D ...

Troubleshooting Vue Router sub-routes behaving unexpectedly

Having some issues with setting up sub-routes using vue-router. It seems that the parent route component is being rendered instead of the declared sub-route component. It appears that there must be a component declared for the parent route to display anyth ...

What is a more effective approach for managing form data with React's useState hook?

Seeking a more efficient solution to eliminate redundancy in my code. Currently, I am utilizing useState() for managing user data, which results in repetition due to numerous fields. Below is a snippet of my current code: const [lname, setLast] = useState& ...

Tips for transferring data and events between named views within Vue Router

I have a layout structured like this: .------------------------+----------------. | Current Tab Title | Controls | +------------------------+----------------+ | Tab1 Tab2 [Tab3] | +---------------------------------------- ...

Vue.js The function "addToCart" is not present in the current instance

I'm having some trouble creating a component and keep getting an error message stating that "addToCart" is not defined. Even though I have defined it within the same component, the error persists. Can anyone help me with this issue? Vue.component("so ...

Error: The variable "prisma" is not defined in this context - Next.js version 14

While working with Prisma and next.js 14, I encountered an issue with the Stripe payment API. The error message ReferenceError: prisma is not defined popped up. How can I resolve this? import { NextApiRequest, NextApiResponse } from "next" import ...

Is it feasible to utilize GraphQL subscriptions with Azure Functions?

Exploring the potential of implementing GraphQL subscriptions on Azure Functions. Unfortunately, it seems that apollo-server-azure-functions may not be compatible. Are there any other options or strategies to successfully enable this functionality? ...

Converting the first page of the Vuepress README.doc from yaml format to markdown format document

I am struggling to locate instructions on customizing the homepage of Vuepress. While I appreciate its layout, the .yaml format is preventing me from adding links. Is there a way to include links? Or even better, can the page be converted to markdown whi ...