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

回答 7 浏览 4.4万 2020-10-18

找不到任何东西来解决这个看起来很明显的问题。

刚刚从Vue 2升级到Vue 3和带Typescript的Vuex。

this.$store似乎无法访问,尽管遵循了Vue 3的说明。

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

感谢任何明智的建议 :)

文件的结构

├── .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

这是我第一次正确使用eslint,所以我不确定我的设置是否正确。我最终在/client和/server目录下使用了不同的tsconfig。

客户端/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"
  ]
}
Narkanister 提问于2020-10-18
顺便提一下,看一下官方软件库总是值得的,因为你可能会发现对你有帮助的信息。例如,打字的问题目前有记录 here ^^。Jens 2020-10-18
也许这对stackoverflow.com/questions/56002310/…会有帮助。Serkan KONAKCI 2021-07-23
根据官方文档,你可能需要为全局存储增加类型定义。Ricardo Martínez 2022-01-24
7 个回答
#1楼 已采纳
得票数 74

shims-vue.d.ts文件旁边创建另一个名为shims-vuex.d.ts的文件,其内容如下:

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

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

更多信息请查看Typescript支持部分,以了解更多细节。

Boussadjra Brahim 提问于2020-10-18
Boussadjra Brahim 修改于2020-12-02
只是补充说明,在VSCode上,我不得不重新加载窗口,这样才能工作。Vinicius Bazanella 2022-07-11
#2楼
得票数 15

我也有过类似的错误,但在VS Code中。 从Vuex 4开始,这是首选的方法。

// 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>
  }
}

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

我不得不再次禁用然后再启用Vetur

jeti 提问于2021-03-03
我做了F1 > Vetur > Restart VLS,这也起到了作用,但你的回答让我找到了正确的方向!你的答案是什么?Marc 2021-06-14
这给我带来了更多的错误,例如`找不到模块'./App.vue'的声明文件`。Caleb Jay 2021-10-15
#3楼
得票数 2

试着加入

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

在安装之前,在你的main.ts文件中。这个方法在我这边很有效,最后的代码看起来像

...
let app = createApp(App);
app.provide("$store", store);
app.use(store);
app.mount("#app");
Old Panda 提问于2021-08-25
#4楼
得票数 1

对于那些通过vue-class-component和/或vue-property-decorator使用VS Code和Vue与TypeScript的人来说,可能没有必要增加类型声明。这个问题可以用tsconfig.json来解决。 也就是用它的include属性。

如果你看到的这个错误的文件不在include属性的globs列表中,你会看到缺失的this.$store定义错误。

请注意,在下面的代码中,如果你从include数组中省略了tests/....球,那么错误就会出现在包含这个球的文件中。如果你把这个glob加回来,错误就会消失。

   "include": ["src/**/*.ts", "src/**/*.vue", "tests/e2e/.fixtures/**/*.ts"]
Valentine Shi 提问于2022-02-03
这为我节省了时间,谢谢你!Kwaadpepper 2022-06-11
#5楼
得票数 0

我做了与上述解决方案相同的事情,但除此之外,我还为该应用程序创建了一个globalProperty。

import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
import store from './store';

const app = createApp(App);
app.config.globalProperties.$store = store;
app.use(router).mount('#app');
Lucas Kenji 提问于2021-05-29
这个文件在哪里,叫什么?谢谢!v3nt 2022-03-30
#6楼
得票数 0

我在尝试用typecript和options API配置vuex时遇到了很多问题。无论你使用哪种API,我都强烈建议你使用Pinea,因为它是一个可以使用typescript的解决方案,与Vuex非常相似。

Mithsew 提问于2022-02-09
#7楼
得票数 -1

Vuex并没有为this.$store属性提供开箱即用的类型。当与TypeScript一起使用时,你必须声明你自己的模块增强。 参考资料

违章动物 提问于2021-12-11