Vue.js 3 and typescript : Property '$store' does not exist on type 'ComponentPublicInstance

35,703

Solution 1

Next to shims-vue.d.ts file create another file called shims-vuex.d.ts with the following content :

import { Store } from '@/store';// path to store file

declare module '@vue/runtime-core' {
  interface ComponentCustomProperties {
    $store: Store;
  }
}

For more check the Typescript support section for more details

Solution 2

I had a similar error but in VS Code. As of Vuex 4, this is the preferred method:

// vuex-shim.d.ts

import { ComponentCustomProperties } from 'vue'
import { Store } from 'vuex'

declare module '@vue/runtime-core' {
  // Declare your own store states.
  interface State {
    count: number
  }

  interface ComponentCustomProperties {
    $store: Store<State>
  }
}

Docs: https://next.vuex.vuejs.org/guide/migrating-to-4-0-from-3-x.html#typescript-support

And I had to disable then enable Vetur again.

Solution 3

Try adding

app.provide("$store", store);

in your main.ts file before mounting. This method works on my side and the final code looks like

...
let app = createApp(App);
app.provide("$store", store);
app.use(store);
app.mount("#app");

Solution 4

For those using VS Code and Vue with TypeScript via vue-class-component and/or vue-property-decorator there may be no need in adding more type declarations. The issue could be solved with tsconfig.json . Namely with its include property.

You will see missing this.$store definition error if the file you are seeing this error is not in the list of globs in the include property.

Note as in the code below if you omit the tests/.... glob from the include array the error will appear in the files matcing this glob. If you add the glob back the error will disappear.

   "include": ["src/**/*.ts", "src/**/*.vue", "tests/e2e/.fixtures/**/*.ts"]
Share:
35,703

Related videos on Youtube

Narkanister
Author by

Narkanister

Updated on July 09, 2022

Comments

  • Narkanister
    Narkanister almost 2 years

    Can't find anything to solve this seemingly obvious issue.

    Just upgraded from Vue 2 to Vue 3 and Vuex with Typescript.

    this.$store doesn't seem to be accessible, despite following the Vue 3 instructions.

    ERROR in src/components/FlashMessages.vue:28:25 TS2339: Property '$store' does not exist on type 'ComponentPublicInstance<{}, {}, {}, { getAllFlashMessages(): Word; }, {}, EmitsOptions, {}, {}, false, ComponentOptionsBase<{}, {}, {}, { getAllFlashMessages(): Word; }, {}, ComponentOptionsMixin, ComponentOptionsMixin, EmitsOptions, string, {}>>'.

        26 |     computed: {
        27 |         getAllFlashMessages (): FlashType {
      > 28 |             return this.$store.getters.getFlashMessages;
           |                         ^^^^^^
        29 |         },
        30 |     },
        31 | 
    

    main.ts

    import { createApp } from 'vue'
    import App from './App.vue'
    import './registerServiceWorker'
    import router from './router'
    import store from './store'
    import './assets/styles/index.css'
    
    const app = createApp(App)
    
    app.use(store)
    app.use(router)
    app.mount('#app')
    

    store.ts

    import { createStore } from 'vuex'
    import FlashType from '@/init'
    
    export default createStore({
        state: {
            flashMessages: [] as FlashType[],
        },
    
        getters: {
            getFlashMessages (state) {
                return state.flashMessages
            }
        },
    

    FlashMessages.vue

    <script lang="ts">
    import { defineComponent } from "vue";
    import FlashType from "@/init";
    
    export default defineComponent({
        name: "FlashMessages",
    
        data () {
            return {};
        },
    
        computed: {
            getAllFlashMessages (): FlashType {
                return this.$store.getters.getFlashMessages;
            },
        },
    

    init.ts

    export type FlashType = {
        kind: 'success' | 'error';
        message: string;
        time: number;
    }
    

    Any wisdom appreciated :)

    File structure

    ├── .editorconfig
    ├── client
    │   ├── babel.config.js
    │   ├── CONTRACTS.md
    │   ├── cypress.json
    │   ├── jest.config.js
    │   ├── package.json
    │   ├── package-lock.json
    │   ├── postcss.config.js
    │   ├── public
    │   │   ├── favicon.ico
    │   │   ├── index.html
    │   │   └── robots.txt
    │   ├── README.md
    │   ├── src
    │   │   ├── App.vue
    │   │   ├── assets
    │   │   │   ├── logo.png
    │   │   │   └── styles
    │   │   │       └── index.css
    │   │   ├── components
    │   │   │   ├── admin
    │   │   │   │   ├── AdminAdd.vue
    │   │   │   │   ├── AdminList.vue
    │   │   │   │   ├── AdminWord.vue
    │   │   │   │   ├── EmotionAdd.vue
    │   │   │   │   ├── EmotionsList.vue
    │   │   │   │   └── Emotion.vue
    │   │   │   └── FlashMessages.vue
    │   │   ├── init.ts
    │   │   ├── main.ts
    │   │   ├── registerServiceWorker.ts
    │   │   ├── router
    │   │   │   └── index.ts
    │   │   ├── shims-vue.d.ts
    │   │   ├── store
    │   │   │   └── index.ts
    │   │   └── views
    │   │       ├── About.vue
    │   │       ├── Admin.vue
    │   │       ├── Emotions.vue
    │   │       └── Home.vue
    │   ├── tsconfig.json
    │   └── vue.config.js
    ├
    └── server
        ├── api
        ├── api.bundle.js
        ├── index.ts
        ├── logger
        │   └── logger.ts
        ├── models
        ├── nodemon.json
        ├── package.json
        ├── package-lock.json
        ├── router
        │   ├── db.ts
        │   └── emotions.ts
        ├── tsconfig.json
        └── webpack.config.js
    

    This is my first time properly using eslint, so I'm not sure if I've set it up correctly.. I ended up with a different tsconfig in /client and /server directories.

    client/tsconfig.json

    {
      "compilerOptions": {
        "target": "esnext",
        "module": "esnext",
        "strict": true,
        "jsx": "preserve",
        "importHelpers": true,
        "moduleResolution": "node",
        "skipLibCheck": true,
        "esModuleInterop": true,
        "allowSyntheticDefaultImports": true,
        "sourceMap": true,
        "baseUrl": "./",
        "types": [
          "webpack-env",
          "jest"
        ],
        "paths": {
          "@/*": [
            "src/*"
          ]
        },
        "lib": [
          "esnext",
          "dom",
          "dom.iterable",
          "scripthost"
        ]
      },
      "include": [
        "src/**/*.ts",
        "src/**/*.tsx",
        "src/**/*.vue",
        "tests/**/*.ts",
        "tests/**/*.tsx"
      ],
      "exclude": [
        "node_modules"
      ]
    }
    
    • Jens
      Jens over 3 years
      As a side note it's always worth it to have a look at the official repositories, as you may find information that will help you. For example the typing problem is currently documented here ^^.
    • Serkan KONAKCI
      Serkan KONAKCI almost 3 years
    • Ricardo Martínez
      Ricardo Martínez over 2 years
      According to the official docs you may need to augmented types definition for the global store.
  • Marc
    Marc almost 3 years
    I did F1 > Vetur > Restart VLS which also did the trick, but your answer got me in the right direction!
  • Caleb Jay
    Caleb Jay over 2 years
    This caused further errors for me, such as ` Could not find a declaration file for module './App.vue'`
  • v3nt
    v3nt about 2 years
    where and what was this file called? Thanks!
  • Kwaadpepper
    Kwaadpepper almost 2 years
    This saved me time, than you !