Utilizing Typescript with Vue 3's Injection Feature

Using the new Vue 3 Composition API, I have created a "store" for reactive data.

const state = reactive<State>({
  accessToken: undefined,
  user: undefined,
});

export default {
  state: readonly(state),
}

When my app is created, I pass the store to all components:

const app = createApp(App)
  .provide("store", store)
  .use(IonicVue)
  .use(router);

Finally, in a component/view, I inject the store to utilize it.

export default defineComponent({
  name: "Home",
  inject: ["store"],
  components: {
    IonContent,
    IonHeader,
    IonPage,
    IonTitle,
    IonToolbar,
    IonButton,
  },
  computed: {
    email() {
      return this.store.state.user.email;
    },
  },
});

However, when using TypeScript, I encounter an issue with this.store in the computed property email(). The error message states:

Property 'store' does not exist on type 'ComponentPublicInstance<{}, {}, {}, { email(): any; }, {}, EmitsOptions, {}, {}, false, ComponentOptionsBase<{}, {}, {}, { email(): any; }, {}, ComponentOptionsMixin, ComponentOptionsMixin, EmitsOptions, string, {}>>'

Everything works fine when removing the lang="ts" attribute from the <script/> tag, but the error persists. Any suggestions on how to resolve this or what it means?

Thank you in advance!

Answer №1

One suggestion is to set the store as a global property without explicitly injecting it into any child components, as using provide/inject may come with some reactivity challenges:

const app = createApp(App)
  .use(IonicVue)
  .use(router);
app.config.globalProperties.store= store;

declare module '@vue/runtime-core' {
  interface ComponentCustomProperties  {
       store:any // update type accordingly
     }
   }

Then utilize it directly within your component:

export default defineComponent({
  name: "Home",
  components: {
  ...
  },
  computed: {
    email() {
      return this.store.state.user.email;
    },
  },
});
</script>

Answer №2

For those grappling with a similar issue in Vue 3 + TS, I have discovered a workaround that does not require altering the app.config or declaring a new module:

  1. Setting up App.ts
import { createApp, reactive } from 'vue'
import App from './App.vue'

const Store = reactive({
  myProperty: 'my value'
})

createApp(App)
  .provide('Store', Store)
  .mount('#app')
  1. The component accessing the injected reactive object:
<template>
  <div>{{ Store.myProperty }}</div>
</template>

<script lang="ts">
import { IStore } from '@/types'
import { defineComponent, inject } from 'vue'

export default defineComponent({
  name: 'MyComponentName',
  setup() {
    return {
      Store: inject('Store') as IStore,
    }
  },
  created() {
    console.log(this.Store) // will show the `Store` in the console
  }
})
</script>
  1. The type defition for the Store (@/types.ts):
export interface IStore {
  myProperty: string
}

By following these 3 steps, I successfully accessed and modified Store.myProperty using TypeScript without any issues.

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

How can I access the parameter value for the tooltip callback function within echarts?

I am attempting to retrieve the value for this specific Apache EChart from within the callback function of the tooltip formatter. When I manually input the value, the formatting function operates correctly: formatter: (params:any) => `$ ${Math.round(pa ...

What is the best way to select an HTML tag element using the :v-deep() selector?

When I utilize the following: ::v-deep img { ... } it functions but triggers a deprecation warning: [@vue/compiler-sfc] ::v-deep usage as a combinator has been deprecated. Use :deep(<inner-selector>) instead. How can I achieve the same effect using ...

WebStorm fails to identify Vue Material Components' HTML tags

When working with VueMaterial in WebStorm, I've encountered an issue where only the <md-list-item> HTML tag is being recognized while others are not listed in the pop-up. This results in unknown HTML tag warnings when using them. https://i.ssta ...

Exploring ways to utilize array.find by comparing it to a different object

There are two arrays in JavaScript named designs and articles. var designs = [ { design_id:"bwbmbqlujurv", article_id:14782, name:"adidas demogorgon black" }, { design_id:"lg9yba2gkcwr", article_id:14782, name:"harry potter w ...

Include an item in a Vuetify model's array of objects

Currently, I am attempting to store the value of a dynamically loaded radio button into an array of objects. These radio buttons serve as options for a set of questions within a form, and my desired output is as follows: [{"question1":{ " ...

At what point in the VueJS lifecycle do props get updated?

I am encountering an issue with accessing a prop within the mounted hook of the Vue.js lifecycle as it appears to be undefined. My component structure, simplified for clarity, is as follows: export default { props: [ 'columns', ...

What is the best way to save a Map for future use in different components?

Let's say I define an enum like this: export enum SomeEnum { SomeLongName = 1, AnotherName = 2 } Within my display components, I'm utilizing an enum map to translate the enum values into strings for presentation on the web app: enumMap = new Map ...

How to properly log out a user in Vue.js?

Hey there, Currently, I am working with the combination of Laravel and VueJS, but I seem to be facing an issue regarding disconnection. For instance: If I log out from one tab and then switch to another tab, I find that I am still able to carry out actio ...

Tricking Vuejs into triggering a @change event

I possess the following: <input type="radio" :name="activity" v-model="activity" :value="1" v-on:change="callProc(data, data2)" required> Ho ...

Troubleshooting Laravel API Eloquent Where Clause inconsistencies when integrated with Vue

Question: Why is my where clause not working as expected? I am utilizing a Laravel API in conjunction with Vue (using Vuex) for my project. Here is the Controller function: public function specific_client(Request $request) { $id = $request ...

Angular: Troubleshooting blank pages in HTML - What's causing it?

This is the content of my heroes component: <!--The content below is only a placeholder and can be replaced.--> <div style="text-align:center"> <h1> <h2>{{hero.name}} Details</h2> <div><s ...

How can I test for equality with an array item using v-if in Vue.js?

Currently, I am facing a challenge in my Vue.js project where I need to determine if a number is equal to an element within an array. Here is the code snippet that I am working with: <div v-if="someValue != arrayElement"> // </div> I am st ...

What is the best way to pass down SectionList prop types in TypeScript when using React?

I am working on creating a wrapper for SectionList in React Native that needs to accept all the standard props of SectionList along with some custom ones. How can I set up typescript to accommodate this? Here is what I have tried: import React from &apos ...

What could be causing my Vue.js application to not function properly when utilizing the Vue runtime version?

After making a modification to Webpack, I switched my Vue.js version to the runtime version with the following changes: resolve: { extensions: ['.ts', '.js', '.vue', '.json'], alias: { 'vue$&apo ...

Vuetify's autofocus feature is limited to functioning only when the modal is first opened

When attempting to utilize Vuetify's v-text-field with the autofocus attribute, I am facing an issue where it only works the first time. Once I close the dialog, the autofocus functionality no longer works. This is the code snippet I am trying to imp ...

Difficulty in transferring a variable from my JavaScript file to my PHP file

Currently, I am utilizing the Instascan API to scan QR codes with the intention of sending the scanned content to my PHP file. However, regardless of whether I use POST or GET methods, the PHP file does not seem to recognize them and keeps expecting either ...

Ways to position loading animation in the center and create a lightbox effect for the rest of the page

I have implemented a custom loader in CSS with the following styles: .loader { border: 16px solid #f3f3f3; /* Light grey */ border-top: 16px solid #3498db; /* Blue */ border-radius: 50%; width: 80px; height: 80px; animation: spin 2s linear inf ...

What causes TypeScript 3.7.5 to trigger an error while typing a function that accepts an array as a parameter?

I'm facing a perplexing compiler error while trying to define a function that requires an array as its sole argument. Below is a concise scenario to reproduce the issue: http://www.example.com import React from 'react' type FooProps = { ...

Using Angular NgRx - triggering an action from an effect once certain actions yield a result

I'm encountering difficulties in dispatching actions that require results from five other actions (all listed in my effect). Could someone lend a hand? Essentially, I need to trigger an action within the effect only after these five actions have retu ...

Inject the data within Observable<Object> into Observable<Array>

I'm faced with a situation where I have two distinct API endpoints. One endpoint returns a single Card object, while the other endpoint returns an Array of Card objects. My goal is to retrieve the first Card from the single Card endpoint and place it ...