Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save iamhabbeboy/79c9eb7f4015cf43a27236c62ed1e23d to your computer and use it in GitHub Desktop.
Save iamhabbeboy/79c9eb7f4015cf43a27236c62ed1e23d to your computer and use it in GitHub Desktop.
Vuex 4 - Boilerplate Typescript

Vuex 4 boilerplate using Vue3 and typed modules with TypeScript

With Modules

📦src
 ┣ 📂store
 ┃ ┣ 📂modules
 ┃ ┃ ┗ 📂generic_module
 ┃ ┃ ┃ ┣ 📜actions.ts
 ┃ ┃ ┃ ┣ 📜getters.ts
 ┃ ┃ ┃ ┣ 📜index.ts
 ┃ ┃ ┃ ┗ 📜mutations.ts
 ┃ ┗ 📜index.ts > *root_index.ts*
import { ActionContext, ActionTree } from "vuex";
import { Mutations, MutationTypes } from "./mutations";
import { State } from "./index";
import { RootState } from "@/store";
//(C) - Ações
// [C.1] inserir a definição da ação x no enum
// ==> { setX = "NOMEMODULO__SET_ X" }
export enum ActionTypes {
setValue = "GENERIC__SET_VALUE",
}
// !!! AUGUMENTED ACTION CONTEXT !!!
type AugmentedActionContext = {
commit<K extends keyof Mutations>(
key: K,
payload: Parameters<Mutations[K]>[1]
): ReturnType<Mutations[K]>;
} & Omit<ActionContext<State, RootState>, "commit">;
// [C.2] definir o tipo da ação setX
// ==> [ActionTypes.setX](
// ==> { commit }: AugmentedActionContext,
// ==> payload: TIPO_DE_X
// ==> ): void;
export interface Actions {
[ActionTypes.setValue](
{ commit }: AugmentedActionContext,
payload: any
): void;
}
// [C.3] declara a ação setX
// [ActionTypes.setX]({ commit }, payload) {
// commit(MutationTypes.X, payload);
// },
export const actions: ActionTree<State, RootState> & Actions = {
[ActionTypes.setValue]({ commit }, payload) {
commit(MutationTypes.VALUE, payload);
},
};
<template>
<input type="text" name="test" id="test" v-model="data" />
</template>
<script lang="ts">
import { defineComponent, ref } from "vue";
import useStore from "path/to/store/index";
import { ActionTypes as ModuleA } from "path/to/module/index";
export default defineComponent({
name: "name",
components: {},
props: {},
setup() {
const data = ref("");
// declare useStore inside composition API setup()
const store = useStore();
// this will be acording with the module's action.ts
store.dispatch(ModuleA.setData, data.value);
// this will be acording with the module's getters.ts
console.log(store.getters.data);
return { data };
},
});
</script>
import { GetterTree } from "vuex";
import { State } from "./index";
import { RootState } from "@/store";
// (D) - Getters
// [D.1] - Define o tipo do getter x
// => x(state: S): TIPO_DE_X;
export type Getters<S = State> = {
value(state: S): any;
};
// [D.2] - Declara o getter x
// => x: (state) => {
// => return state.x;
// => },
export const getters: GetterTree<State, RootState> & Getters = {
value: (state) => {
return state.value;
},
};
import { getters, Getters } from "./getters";
import { mutations, Mutations } from "./mutations";
import { actions, Actions, ActionTypes } from "./actions";
import {
Store as VuexStore,
Module,
CommitOptions,
DispatchOptions,
} from "vuex";
import { RootState } from "@/store";
// PARA ALTERAR A STORE
// (A) - Alterar o state ./
// (B) - Alterar as mutações ./mutations.ts
// (C) - Alterar as ações ./actions.ts
// (D) - Alterar os getters ./getters.ts
// !!! não mecher nos snipets de código com comentário em maiusculo !!!
//[A.1] inclui valor na interface do state
// ==> x: TIPO_DE_X
interface State {
value: any;
}
//[A.2] declara o valor no objeto do state
// ==> x: VALOR_DE_X
const state: State = {
value: "",
};
const generic_module: Module<State, RootState> = {
state,
mutations,
actions,
getters,
};
export { State, ActionTypes, Store };
export default generic_module;
// !!! CONFIGURA TIPAGEM DA STORE !!!
type Store<S = State> = Omit<
VuexStore<S>,
"commit" | "getters" | "dispatch"
> & {
commit<K extends keyof Mutations, P extends Parameters<Mutations[K]>[1]>(
key: K,
payload: P,
options?: CommitOptions
): ReturnType<Mutations[K]>;
} & {
getters: {
[K in keyof Getters]: ReturnType<Getters[K]>;
};
} & {
dispatch<K extends keyof Actions>(
key: K,
payload: Parameters<Actions[K]>[1],
options?: DispatchOptions
): ReturnType<Actions[K]>;
};
// this should be in your main.ts file
import { store, key } from "path/to/store/index";
const app = createApp(App);
app.use(store, key);
import { MutationTree } from "vuex";
import { State } from "./index";
// (B) - Mutações
// [B.1] inserir a definição da mutação X no enum
// ==> { X = "SET_ X" }
export enum MutationTypes {
VALUE = "SET_VALUE",
}
// [B.2] definir o tipo da mutação X
// ==> [MutationTypes.X](state: S, payload: TIPO_DE_X): void;
export type Mutations<S = State> = {
[MutationTypes.VALUE](state: S, payload: any): void;
};
// [B.3] declarar a mutação X
// ==> [MutationTypes.X](state, payload) {
// ==> state.x = payload;
// ==> },
export const mutations: MutationTree<State> & Mutations = {
[MutationTypes.VALUE](state, payload) {
state.value = payload;
},
};
import { InjectionKey } from "vue";
import {
createStore,
Store as VuexStore,
useStore as baseUseStore,
} from "vuex";
import generic, {
State as GenericState,
Store as GenericStore,
} from "./modules/__generic_module";
import other, {
State as OtherState,
Store as OtherStore,
} from "./modules/other_module";
// define tipos pro state da store
export interface RootState {
debitos: GenericState;
/* other: OtherState; */
}
export type RootStore = GenericStore<Pick<RootState, "debitos">>;
// & OtherStore<Pick<RootState, "other">> &
// define injection key
export const key: InjectionKey<VuexStore<RootState>> = Symbol();
export const store = createStore<RootState>({
modules: {
generic,
// other
},
});
// o usar `import useStore from '@store'`
export default function useStore(): RootStore {
return baseUseStore(key);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment