Skip to content

Commit

Permalink
Merge pull request #3 from zWingz/support
Browse files Browse the repository at this point in the history
feat: support mapState/mapMutations and parameters checking
  • Loading branch information
zWingz authored Jun 8, 2020
2 parents 05fe850 + 166b8df commit 711cc33
Show file tree
Hide file tree
Showing 7 changed files with 199 additions and 48 deletions.
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# CHANGELOG

## Release 0.0.5

### Feature

- support `mapMutations`

### Enhance

- support `mapActions` parameter type checking

### Bugfix

- `mapStats` return a function

## Release 0.0.4

- support `mapState` `mapGetters` `mapActions` and `dispatch`
21 changes: 13 additions & 8 deletions dev/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,33 @@
</div>
</template>

<script>
// @ts-check
import { mapGetters, mapActions } from './store'
export default {
<script lang="ts">
import Vue from 'vue';
import { mapGetters, mapActions, mapState, mapMutations } from './store'
export default Vue.extend({
computed: {
...mapState('user', ['username']),
...mapGetters('user', ['getUsername']),
...mapGetters(['getName']),
...mapGetters('user', {
getUsername1: 'getUsername'
})
}),
},
mounted() {
console.log(this.getName);
console.log(this.getUsername);
console.log(this.getUsername1);
this.updateUsername('updateUsername')
this.username
this.updateUserMeta({ age: 21 });
// this.()
},
methods: {
...mapActions('user', ['setUsername']),
...mapActions(['setName'])
...mapActions(['setName']),
...mapActions('user', ['updateUsername', 'updateUserMeta']),
...mapMutations('user', ['setUsername', 'setUserMeta'])
}
}
});
</script>

<style>
Expand Down
22 changes: 19 additions & 3 deletions dev/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,32 @@ const state = {
namespaced: true,
state: {
username: 'this is username',
meta: {
age: 20,
address: 'address'
}
},
actions: {
setUsername({ commit }, payload) {
updateUsername({ commit }, payload: string) {
commit('setUsername', payload);
},
setUsername2({ commit }, payload) {
updateUserMeta({ commit }, payload: { age?: number; address?: string }) {
commit('setUsername', payload);
},
test: {
root: true,
handler({ commit }) {}
}
},
mutations: {
setUsername(state, payload) {
state.username = payload
},
setUserMeta(state, payload: { age?: number; address?: string }) {
state.meta = {
...state.meta,
...payload
};
}
},
getters: {
Expand All @@ -61,4 +75,6 @@ const state = {
};

const s = new EnhanceStore(state);
export const { mapGetters, store, mapActions } = s;
export const { mapGetters, store, mapActions, mapMutations, mapState } = s;

mapActions('user', ['updateUserMeta']).updateUserMeta
105 changes: 69 additions & 36 deletions src/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,40 +4,21 @@ import {
mapActions,
mapGetters,
mapState,
ActionHandler,
ActionObject,
mapMutations,
} from 'vuex';

type PromiseAction<T> = T extends ActionHandler<any, any>
? (...args: any) => Promise<ReturnType<T>>
: T extends ActionObject<any, any>
? (...args: any) => Promise<ReturnType<T['handler']>>
: never;

type Module<T extends StoreOptions<any>> = T['modules'];
type Getters<T extends StoreOptions<any>> = T['getters'];
type Actions<T extends StoreOptions<any>> = T['actions'];
type State<T extends StoreOptions<any>> = T['state'];

type OnlyString<T> = keyof T & string;

type GetKeys<T extends StoreOptions<any>, E, K> = E extends OnlyString<
Module<T>
>
? K extends OnlyString<Module<T>[E]>
? OnlyString<Module<T>[E][K]>
: never
: never;


type GetObject<T extends StoreOptions<any>, E, K> = E extends OnlyString<
Module<T>
>
? K extends OnlyString<Module<T>[E]>
? Module<T>[E][K]
: never
: never;

import {
PromiseAction,
Mutation,
Module,
Getters,
Actions,
State,
Mutations,
OnlyString,
GetKeys,
GetObject,
} from './types';

/**
* methods override ordering must be
Expand All @@ -46,9 +27,11 @@ type GetObject<T extends StoreOptions<any>, E, K> = E extends OnlyString<
*/
export class EnhanceStore<S, T extends StoreOptions<S>> {
store: _Store<S>;

constructor(s: T) {
this.store = new _Store(s);
}

dispatch<
E extends OnlyString<Module<T>>,
U extends GetKeys<T, E, 'actions'>
Expand All @@ -66,10 +49,12 @@ export class EnhanceStore<S, T extends StoreOptions<S>> {
mapGetters<Map extends Record<string, K>, K extends OnlyString<Getters<T>>>(
k: Map
): { [k in keyof Map]: () => ReturnType<Getters<T>[Map[k]]> };

// keys
mapGetters<Keys extends OnlyString<Getters<T>>>(
k: Keys[]
): { [k in Keys]: () => ReturnType<Getters<T>[k]> };

// namespace mapper
mapGetters<
NameSpace extends OnlyString<Module<T>>,
Expand All @@ -83,6 +68,7 @@ export class EnhanceStore<S, T extends StoreOptions<S>> {
GetObject<T, NameSpace, 'getters'>[Map[k]]
>;
};

// namespace keys
mapGetters<
NameSpace extends OnlyString<Module<T>>,
Expand All @@ -93,20 +79,24 @@ export class EnhanceStore<S, T extends StoreOptions<S>> {
): {
[K in Keys]: () => ReturnType<GetObject<T, NameSpace, 'getters'>[K]>;
};

mapGetters(k: any, u?: any) {
return mapGetters(k, u);
}

/**
* mapActions
*/
// mapper
mapActions<Map extends Record<string, K>, K extends OnlyString<Actions<T>>>(
k: Map
): { [k in keyof Map]: PromiseAction<Actions<T>[Map[k]]> };

// keys
mapActions<Keys extends OnlyString<Actions<T>>>(
k: Keys[]
): { [k in Keys]: PromiseAction<Actions<T>[k]> };

// namespace mapper
mapActions<
NameSpace extends OnlyString<Module<T>>,
Expand All @@ -120,6 +110,7 @@ export class EnhanceStore<S, T extends StoreOptions<S>> {
GetObject<T, NameSpace, 'actions'>[Map[k]]
>;
};

// namespace keys
mapActions<
NameSpace extends OnlyString<Module<T>>,
Expand All @@ -128,20 +119,61 @@ export class EnhanceStore<S, T extends StoreOptions<S>> {
k: NameSpace,
u: Keys[]
): { [K in Keys]: PromiseAction<GetObject<T, NameSpace, 'actions'>[K]> };

mapActions(k: any, u?: any) {
return mapActions(k, u);
}

/**
* mapMutations
*/
// mapper
mapMutations<Map extends Record<string, K>, K extends OnlyString<Mutations<T>>>(
k: Map
): { [k in keyof Map]: Mutation<Mutations<T>[Map[k]]> };

// keys
mapMutations<Keys extends OnlyString<Mutations<T>>>(
k: Keys[]
): { [k in Keys]: Mutation<Mutations<T>[k]> };

// namespace mapper
mapMutations<
NameSpace extends OnlyString<Module<T>>,
Map extends Record<string, Keys>,
Keys extends GetKeys<T, NameSpace, 'mutations'>
>(
k: NameSpace,
m: Map
): {
[k in keyof Map]: Mutation<GetObject<T, NameSpace, 'mutations'>[Map[k]]>;
};

// namespace keys
mapMutations<
NameSpace extends OnlyString<Module<T>>,
Keys extends GetKeys<T, NameSpace, 'mutations'>
>(
k: NameSpace,
u: Keys[]
): { [K in Keys]: Mutation<GetObject<T, NameSpace, 'mutations'>[K]>; }
mapMutations(k: any, u?: any) {
return mapMutations(k, u);
}

/**
* mapState
*/
// mapper
mapState<Map extends Record<string, K>, K extends OnlyString<State<T>>>(
k: Map
): { [k in keyof Map]: State<T>[Map[k]] };
): { [k in keyof Map]: () => State<T>[Map[k]] };

// keys
mapState<Keys extends OnlyString<State<T>>>(
k: Keys[]
): { [k in Keys]: State<T>[k] };
): { [k in Keys]: () => State<T>[k] };

// nanespace mapper
mapState<
NameSpace extends OnlyString<Module<T>>,
Expand All @@ -150,15 +182,16 @@ export class EnhanceStore<S, T extends StoreOptions<S>> {
>(
k: NameSpace,
m: Map
): { [k in keyof Map]: GetObject<T, NameSpace, 'state'>[Map[k]] };
): { [k in keyof Map]: () => GetObject<T, NameSpace, 'state'>[Map[k]] };

// namespace keys
mapState<
NameSpace extends OnlyString<Module<T>>,
Keys extends GetKeys<T, NameSpace, 'state'>
>(
k: NameSpace,
u: Keys[]
): { [K in Keys]: GetObject<T, NameSpace, 'state'>[K] };
): { [K in Keys]: () => GetObject<T, NameSpace, 'state'>[K] };
mapState(k: any, u?: any) {
return mapState(k, u);
}
Expand Down
45 changes: 45 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { StoreOptions, ActionHandler, ActionObject } from 'vuex';


type Payload<T> = T extends (arg1: any, arg2: any) => any ? Parameters<T>[1] : never


export type PromiseAction<T> = T extends ActionHandler<any, any>
? Payload<T> extends undefined
? () => Promise<ReturnType<T>>
: (payload: Payload<T>) => Promise<ReturnType<T>>
: T extends ActionObject<any, any>
? Payload<T['handler']> extends undefined
? () => Promise<ReturnType<T['handler']>>
: (payload: Payload<T['handler']>) => Promise<ReturnType<T['handler']>>
: never;

export type Mutation<T> = T extends (...args: any[]) => void
? Payload<T> extends undefined
? () => void
: (payload: Payload<T>) => void
: never;

export type Module<T extends StoreOptions<any>> = T['modules'];
export type Getters<T extends StoreOptions<any>> = T['getters'];
export type Actions<T extends StoreOptions<any>> = T['actions'];
export type State<T extends StoreOptions<any>> = T['state'];
export type Mutations<T extends StoreOptions<any>> = T['mutations'];

export type OnlyString<T> = keyof T & string;

export type GetKeys<T extends StoreOptions<any>, E, K> = E extends OnlyString<
Module<T>
>
? K extends OnlyString<Module<T>[E]>
? OnlyString<Module<T>[E][K]>
: never
: never;

export type GetObject<T extends StoreOptions<any>, E, K> = E extends OnlyString<
Module<T>
>
? K extends OnlyString<Module<T>[E]>
? Module<T>[E][K]
: never
: never;
32 changes: 32 additions & 0 deletions tests/mapActions.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { EnhanceStore } from '../src/store';
const state = {
actions: {
setName({ commit }, payload) {
},
setName2({ commit }, payload) {
},
},
modules: {
user: {
namespaced: true,
actions: {
updateUsername({ commit }, payload: string) {},
updateUserMeta(
{ commit },
payload: { age?: number; address?: string }
) {},
test: {
root: true,
handler({ commit }, payload: string) {},
},
},
},
},
};

const s = new EnhanceStore(state);
export const { mapGetters, store, mapActions, mapMutations, mapState } = s;

mapActions('user', ['updateUserMeta']).updateUserMeta({ age: 1 });
mapActions('user', ['updateUsername']).updateUsername('123');
mapActions('user', ['test']).test('fd');
3 changes: 2 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@
"declarationDir": "lib",
"strict": true,
"moduleResolution": "node",
"noImplicitAny": false,
// "declaration": true,
// "importHelpers": true,
"experimentalDecorators": true
},
"include": ["src"],
"include": ["src", "dev"],
"exclude": ["node_modules"]
}

0 comments on commit 711cc33

Please sign in to comment.