Last active
July 19, 2017 08:41
-
-
Save ghetolay/3a1ff05fa55d325da95132143e020cfe to your computer and use it in GitHub Desktop.
Pattern to build actions for ngrx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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