Skip to content

Instantly share code, notes, and snippets.

@ghetolay
Last active July 19, 2017 08:41
Show Gist options
  • Save ghetolay/3a1ff05fa55d325da95132143e020cfe to your computer and use it in GitHub Desktop.
Save ghetolay/3a1ff05fa55d325da95132143e020cfe to your computer and use it in GitHub Desktop.
Pattern to build actions for ngrx
export interface Action<T> {
type: T;
}
export interface PayloadAction<T, R> {
readonly type: T;
payload: R;
}
export interface ActionFactory<T> {
(): Action<T>;
type: T;
}
export interface PayloadActionFactory<T, R> {
(payload: R): PayloadAction<T, R>;
type: T;
}
export function actionFactoryBuilder<T extends string>(type: T | ''): ActionFactory<T> {
const actionFactory = function(): Action<T> {
return { type: <T>type };
};
(<any>actionFactory).type = type;
return <ActionFactory<T>>actionFactory;
}
export function payloadactionFactoryBuilder<P, T extends string>(type: T|'', payloadFunc: (p: P) => P):
{ type: T, (p: P): PayloadAction<T, P> };
export function payloadactionFactoryBuilder<P, T extends string, V1>(type: T|'', payloadFunc: (v1: V1) => P):
{ type: T, (v1: V1): PayloadAction<T, P> };
export function payloadactionFactoryBuilder<P, T extends string, V1, V2>(type: T|'', payloadFunc: (v1: V1, v2: V2) => P):
{ type: T, (v1: V1, v2: V2): PayloadAction<T, P> };
export function payloadactionFactoryBuilder<P, T extends string, V1, V2, V3>(type: T|'', payloadFunc: (v1: V1, v2: V2, v3: V3) => P):
{ type: T, (v1: V1, v2: V2, v3: V3): PayloadAction<T, P> };
export function payloadactionFactoryBuilder<P, T extends string, V1, V2, V3, V4>(type: T|'', payloadFunc: (v1: V1, v2: V2, v3: V3, v4: V4) => P):
{ type: T, (v1: V1, v2: V2, v3: V3, v4: V4): PayloadAction<T, P> };
export function payloadactionFactoryBuilder<P, T extends string, V1, V2, V3, V4>(type: T|'', payloadFunc: (v1: V1, v2?: V2, v3?: V3, v4?: V4) => P) {
const actionBuilder = function(v1: V1, v2: V2, v3: V3, v4: V4) {
return {
payload: payloadFunc(v1, v2, v3, v4),
type: <T>type
};
};
(<any>actionBuilder).type = <T>type;
return actionBuilder;
}
const Action1 = actionFactoryBuilder('ACTION1');
const Action2 = payloadactionFactoryBuilder('ACTION2', (p: number) => p);
/* Here we had to use a function mostly for typings but also allow user to define some logic to build the payload: asserting min/max value for example.
I'm targeting something like :
*/
payloadactionFactoryBuilder<T extends string, R, P...>(name: T, paylodFunc?: (...P) => R): PayloadAction<T, R);
/* possible usage would be */
payloadactionFactoryBuilder<{n: number, s: string}>('ACTION2');
/* or */
payloadactionFactoryBuilder('ACTION2', (n: number, s: string) => {n: n < 0 ? 0 : n, s});
/* Here we need to do some boilerplate by repeting the structure of our actions
* This should be replaced with future ts version with something like :
* `type Actions = returnType Action1 | returnType Action2`
*/
type Actions = Action<'ACTION1'> | PayloadAction<'ACTION2', number>;
// reducer
function reducer(state:State, action: Actions) {
switch(action.type) {
case Action1.type :
//
case Action2.type :
//
}
}
// dispatch
store.dispatch(Action1());
store.dispatch(Action2(10));
// effects
@Effect()
this.actions$
.ofType(Action1.type);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment