扩展或覆盖vuex商店

时间:2018-02-11 18:32:22

标签: typescript vue.js vuex

我在我的应用中使用Vuex进行状态管理,而且我也使用TypeScript,理想情况下,我希望能够引用商店的强类型版本,而不仅仅是默认情况下状态是'任何'等...我知道如何扩展'要添加的类型定义,例如新属性,但我正在努力寻找一种方法(如果可能的话)强制使用'强制'默认Store上的强类型商店定义。我只是得到错误,说后续定义必须具有相同的类型,我想这是可以理解的,但我很懒,想要一些智能感知! ; - )

我读过的大多数文档说它不可能覆盖已在类型定义文件中定义的类型,并且您只能添加其他属性,例如,但是我有什么方法可以之后可能是这样还是其他?否则,我将不得不记住我的方法/行动的所有名称等。

2 个答案:

答案 0 :(得分:0)

虽然您无法重新定义现有属性,但您可以将$store属性的类型版本定义为未键入版本的别名:

import Vue from 'vue'
import * as Vuex from 'vuex'

declare module "vue/types/vue" {
    interface Vue {
        $typedStore: Vuex.Store<{
            count: number
        }>;
    }
}

Object.defineProperty(Vue.prototype, "$storeTyped", {
    get: function(this: Vue) {
        return this.$store;
    }
})


const App = new Vue({
    computed: {
        counter: function (this: Vue) {
            return this.$storeTyped.state.count; // Works and is typed
        }
    },
    // Other stuff
});

答案 1 :(得分:0)

我知道这是一个老问题,但是我希望我能以某种方式帮助某人。在看了Titian Cernicova-Dragomir的回答后,我实际上必须执行此解决方案。我只是想强迫Vuex只允许我定义的动作。我相信我找到了一种方法,特别是针对您说“ ”的部分,否则,我将必须记住我的方法/操作 的所有名称我的案例特别强调动作部分。我尚未对此进行彻底的测试,但到目前为止,它似乎可以正常工作。

比方说,您有如下代码,您想要在Vuex商店中存储人员和汽车,并且只希望执行用于存储人员和汽车的操作。为简单起见,我从代码中删除了很多内容,并将它们全部放在一个文件中。

一个明显的问题是,这可能仅适用于我使用的Vuex版本,但我不知道,我还没有测试那么远。但是很明显,如果Dispatch和Store构造函数的定义发生了更改,则可能也必须更改代码。

节点,该代码已在打字稿3.5.3,vue 2.6.10和vuex 3.1.2上进行了测试

import * as Vuex from 'vuex';

/** let's assume we have */
type Person = { name: string, age: number };
type Car = { make: string, year_made: number };

/** let us also assume we want to only allow these 2 actions */
enum ALLOWED_ACTIONS {
    STORE_CARS = 'actionStoreCars',
    STORE_PEOPLE = 'actionStorePeople'
}

/** 
 * defining a condition type that can be either 
 * an array or people or an array of cars 
 * */
export type Entities<T> = T extends Person | Car ? T[] : unknown;




/**
 * extending Vuex's dispatch function so that it will only allow
 * - The actions defined in the enum ALLOWED_ACTIONS
 * - A payload that is ONLY either of 
 *      > Person[]
 *      > Car[]
 * that is, we create a new dispatch that only allows actions that will result 
 * in the storage of either array of Persons or array of Cars only, nothing else.
 */
export interface Dispatch {
    /** If actions is ALLOWED_ACTIONS.STORE_CARS then only allow payload of type Entities<Car> */
    (   action: ALLOWED_ACTIONS.STORE_CARS , 
        payload: Entities<Car>, 
        options?: Vuex.DispatchOptions ): Promise<any>;


    /** If actions is ALLOWED_ACTIONS.STORE_PEOPLE then only allow payload of type Entities<Person> */
    (   action: ALLOWED_ACTIONS.STORE_PEOPLE , 
        payload: Entities<Person>, 
        options?: Vuex.DispatchOptions ): Promise<any>;

    /** this comes from the original definition of Dispatch */
    <P extends Vuex.Payload>(payloadWithType: P, options?: Vuex.DispatchOptions): Promise<any>;
}

/**
 * creating my own version of Vuex's store that uses the new defined dispatch above
 */
export class NewVuexStore extends Vuex.Store<any>  {
    dispatch: Dispatch;
    constructor(options: Vuex.StoreOptions<any>) {
        super(options);
        this.dispatch = Vuex.Store.prototype.dispatch;
    }
}

然后这就是实现新商店的方式。

/** this would be in the index.ts from where your store is defined */
// export default new Vuex.Store({...} // I commented this out just to show where the new change is made in here
export default new NewVuexStore({...})

然后是实现

/** 
 * this is just to give clarity for a quick check if the code works
 * */

 /** create your array of Cars */
const cars : Entities<Car> = [];
cars.push({make: 'aaa', year_made: 1994});
cars.push({make: 'bbb', year_made: 1995});
cars.push({make: 'ccc', year_made: 1996});

 /** create array of Persons */
const people : Entities<Person> = [];
people.push({name: 'Tom', age: 49});
people.push({name: 'Tim', age: 29});
people.push({name: 'Bob', age: 9});

/** store cars and people in the Vuex store
 * this dispatches will succeed
 */
store.dispatch(ALLOWED_ACTIONS.STORE_CARS, cars);
store.dispatch(ALLOWED_ACTIONS.STORE_PEOPLE, people);

/** these cause errors, even VS Codes underlines them with errors */
store.dispatch(ALLOWED_ACTIONS.STORE_PEOPLE, cars); // cannot store cars when you said you are storing people
store.dispatch('not_allowed', people);
store.dispatch('not_allowed', cars);
store.dispatch('not_allowed');
store.dispatch('');