Я создаю приложение, используя vuejs2, vuex и машинопись в визуальный студийный код. У меня установлено расширение ветур. Я создал файл определения, чтобы дать мне intellisense для большей части моего проекта, но я не смог понять, как добавить мое хранилище vuex в intellisense. Я прочитал Документация по определению, но мне не удалось вместе решить, как я могу это сделать. Моя цель - получить возможность использовать intellisense для чего угодно в this.$store.. В настоящее время ветур предоставляет intellisense для state, getters и т. д., Но не предоставляет intellisense для следующего уровня (например, this.$store.state.TestVariable). Как я могу получить intellisense для моего магазина vuex?
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
export default new Vuex.Store({
state: {
Contract: new Library.Model.Entity.Contract()
}
});
<template>
<contract-line></contract-line>
</template>
<script lang = "ts">
import Vue from 'vue';
import Vuex from 'vuex';
import store from '../store/ContractManagementStore';
import ContractLine from "./ContractLine.vue";
export default Vue.extend({
name: 'contract-management',
store,
components: {
'contract-line': ContractLine
}
});
</script>
<style>
</style>
<template>
<button v-if = "CanDelete"></button>
</template>
<script lang = "ts">
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
export default Vue.extend({
computed:{
CanDelete(): Boolean {
// Looking for intellisense after this.$store.state.
return this.$store.state.Contract.ContractStatus.Value === Library.Enums.ContractStatus.Draft
}
}
});
</script>
<style>
</style>






Вы можете добиться этого, явно указав свое состояние.
В Contract Management Store.ts
export interface ContractManagementState {
Contract: ContractType;
}
В вашем компоненте:
...
(this.$store as Store<ContractManagementState>).<intellisense here>
К сожалению, вы должны делать это каждый раз, когда получаете доступ к состоянию таким образом. Это связано с тем, как Vuex использует расширение модуля, чтобы объявить о существовании свойства $store в машинописном тексте.
В vuex/types/vue.d.ts:
declare module "vue/types/vue" {
interface Vue {
$store: Store<any>;
}
}
Вы не можете заменить any вашими конкретными типами состояний (в конце концов, это называется модулем увеличение). Возможное решение - использовать геттеры для доступа к вашему магазину. Существует несколько библиотек машинописных текстов для добавления информации о типах к геттерам, мутаторам и действиям, например vuex-typescript и vuex-typex.
Я могу получить intellisense для состояния из этого ... Как мне изменить его, чтобы также получить intellisense для геттеров / мутаторов / действий?
Вы абсолютно правы, в документации Vuex нет рекомендаций, явно рекомендующих геттеры вместо прямого доступа к состоянию. Я отредактировал свой ответ, поэтому мое мнение не похоже на официальную рекомендацию. Тем не менее, я все еще думаю, что пункты, касающиеся отладки и развязки, актуальны. Кроме того, касаясь вашего второго комментария, геттеры просто лучше работают с машинописным текстом. Я рекомендую взглянуть на библиотеку, которую я опубликовал в ответе, которая позволяет вам также вводить мутаторы и действия (за счет некоторого накладного кода)
Я также сталкиваюсь с этой проблемой в эти два дня и не могу вынести отсутствия понимания набора текста this.$store.state.
Решение @ georg-grab дает мне это вдохновение.
- I'm not familiar with TypeScript... So this solution may be silly, but it works.
- My solution can only deal with
this.$store.state, all others such asthis.$store.dispatchstill has no IntelliSense
// store/index.ts
// I will not explain vuex modules here. Please see the doc of Vuex by yourself.
import Vue from 'vue'
import Vuex, {Store} from 'vuex'
import auth, {State as AuthState} from './modules/auth' // State is an interface defined in module.
export interface State {
auth: AuthState
}
Vue.use(Vuex)
export default new Vuex.Store({
modules: {
auth
}
}) as Store<State> // Force TypeScript compiler to recognize this as Store<State> instead of Store<any>.
Затем добавьте глобальный получатель экземпляра через плагин Vue:
// main.ts
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store, { State } from './store'
declare module 'vue/types/vue' { // Tell TypeScript the type of this.$state is our defined 'State'
interface Vue {
$state: State
}
}
const TypedState = { // define a Vue plugin. See https://vuejs.org/v2/guide/plugins.html
install(Vue: any) { // For simplify, didn't pass 'State' via options
Object.defineProperty(Vue.prototype, '$state', { // Add a global getter 'this.$state' in vm
get (): State { return store.state as State } // Force TypeScript compiler to recognize this as our defined 'State'
})
}
}
Vue.use(TypedState)
Теперь вы можете получить доступ к значениям в this.$store.state через this.$state с помощью IntelliSense.
I also want to "overwrite" the interface of
vm.$store(fromStore<any>toStore<State>), but TypeScript seems to has no way to do such thing:declare module 'vue/types/vue' { interface Vue { $store: Store<State> // Error } }
Я не думаю, что согласен с вами в том, что использование геттеров является лучшей практикой. Читая документация, я вижу, что доступ к хранилищу осуществляется напрямую для чтения данных. Я считаю, что лучшая практика больше ориентирована на изменение данных с помощью мутаций / действий, которые я правильно использую в своем коде. У вас есть какая-либо документация Vuex, на которую вы могли бы указать мне, о том, чтобы всегда использовать геттеры для доступа к состоянию?