Skip to content

Commit

Permalink
Updated createReducer api with new method handleType
Browse files Browse the repository at this point in the history
  • Loading branch information
piotrwitek committed Jun 24, 2019
1 parent dfe3240 commit ec10f89
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 58 deletions.
30 changes: 15 additions & 15 deletions .size-snapshot.json
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
{
"dist/typesafe-actions.cjs.development.js": {
"bundled": 8114,
"minified": 4658,
"gzipped": 1124
"bundled": 8152,
"minified": 4675,
"gzipped": 1137
},
"dist/typesafe-actions.cjs.production.js": {
"bundled": 8114,
"minified": 4658,
"gzipped": 1124
"bundled": 8152,
"minified": 4675,
"gzipped": 1137
},
"dist/typesafe-actions.es.production.js": {
"bundled": 7867,
"minified": 4430,
"gzipped": 1079,
"bundled": 7905,
"minified": 4447,
"gzipped": 1090,
"treeshaked": {
"rollup": {
"code": 0,
Expand All @@ -24,13 +24,13 @@
}
},
"dist/typesafe-actions.umd.development.js": {
"bundled": 9434,
"minified": 3599,
"gzipped": 1113
"bundled": 9476,
"minified": 3616,
"gzipped": 1121
},
"dist/typesafe-actions.umd.production.js": {
"bundled": 9434,
"minified": 3599,
"gzipped": 1113
"bundled": 9476,
"minified": 3616,
"gzipped": 1121
}
}
3 changes: 2 additions & 1 deletion benchmarks/150-actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -313,4 +313,5 @@ export const reducer2 = createReducer<number, RootAction>(0)
.handleAction(actions.c22, state => state)
.handleAction(actions.c23, state => state)
.handleAction(actions.c24, state => state)
.handleAction(actions.c25, state => state);
.handleAction(actions.c25, state => state)
.handleType(['c26', 'c27', 'c28', 'c29', 'c30'], (s, a) => s);
10 changes: 5 additions & 5 deletions src/create-reducer.spec.snap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ const initialState = 0;
{
const reducerTest = createReducer(initialState);

const counterReducer1 = reducerTest.handleAction(
const counterReducer1 = reducerTest.handleType(
['ADD', 'INCREMENT'],
(state, action) => state + (action.type === 'ADD' ? action.payload : 1)
);
Expand All @@ -198,16 +198,16 @@ const initialState = 0;
Object.keys({ ...reducerTest.handlers }); // => []

const counterReducer2 = reducerTest
.handleAction(['ADD'], (state, action) => state + action.payload)
.handleAction(['INCREMENT'], (state, _) => state + 1);
.handleType(['ADD'], (state, action) => state + action.payload)
.handleType(['INCREMENT'], (state, _) => state + 1);
// @dts-jest:pass:snap -> Record<"ADD" | "INCREMENT", (state: number, action: T.PayloadAction<"ADD", number> | T.EmptyAction<"INCREMENT"> | T.EmptyAction<"DECREMENT">) => number>
counterReducer2.handlers;
// @dts-jest:pass
Object.keys({ ...counterReducer2.handlers }); // => ["ADD", "INCREMENT"]
// @dts-jest:pass
Object.keys({ ...reducerTest.handlers }); // => []

const counterReducer3 = reducerTest.handleAction(
const counterReducer3 = reducerTest.handleType(
'ADD',
(state, action) => state + action.payload
);
Expand All @@ -218,7 +218,7 @@ const initialState = 0;
// @dts-jest:pass
Object.keys({ ...reducerTest.handlers }); // => []

const counterReducer4 = reducerTest.handleAction(
const counterReducer4 = reducerTest.handleType(
'INCREMENT',
(state, _) => state + 1
);
Expand Down
10 changes: 5 additions & 5 deletions src/create-reducer.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ const initialState = 0;
{
const reducerTest = createReducer(initialState);

const counterReducer1 = reducerTest.handleAction(
const counterReducer1 = reducerTest.handleType(
['ADD', 'INCREMENT'],
(state, action) => state + (action.type === 'ADD' ? action.payload : 1)
);
Expand All @@ -198,16 +198,16 @@ const initialState = 0;
Object.keys({ ...reducerTest.handlers }); // => []

const counterReducer2 = reducerTest
.handleAction(['ADD'], (state, action) => state + action.payload)
.handleAction(['INCREMENT'], (state, _) => state + 1);
.handleType(['ADD'], (state, action) => state + action.payload)
.handleType(['INCREMENT'], (state, _) => state + 1);
// @dts-jest:pass:snap
counterReducer2.handlers;
// @dts-jest:pass
Object.keys({ ...counterReducer2.handlers }); // => ["ADD", "INCREMENT"]
// @dts-jest:pass
Object.keys({ ...reducerTest.handlers }); // => []

const counterReducer3 = reducerTest.handleAction(
const counterReducer3 = reducerTest.handleType(
'ADD',
(state, action) => state + action.payload
);
Expand All @@ -218,7 +218,7 @@ const initialState = 0;
// @dts-jest:pass
Object.keys({ ...reducerTest.handlers }); // => []

const counterReducer4 = reducerTest.handleAction(
const counterReducer4 = reducerTest.handleType(
'INCREMENT',
(state, _) => state + 1
);
Expand Down
90 changes: 59 additions & 31 deletions src/create-reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,20 @@ import {
checkValidActionType,
throwInvalidActionTypeOrActionCreator,
} from './utils/validation';
import { Reducer, Action, Types } from './type-helpers';
import { Reducer, Action, Types, ActionCreator } from './type-helpers';

type CreateReducerChainApi<
type HandleActionChainApi<
TState,
TPrevNotHandledAction extends Action,
TInputAction extends Action,
TRootAction extends Action
> = <
TType extends TPrevNotHandledAction['type'],
TCreator extends (...args: any[]) => TPrevNotHandledAction,
TNextNotHandledAction extends Exclude<
TPrevNotHandledAction,
Action<TType> & ReturnType<TCreator>
>,
TAction extends TPrevNotHandledAction extends Action<TType>
? TPrevNotHandledAction extends ReturnType<TCreator>
? TPrevNotHandledAction
: never
: never
TActionCreator extends (...args: any[]) => TInputAction,
THandledAction extends ReturnType<TActionCreator>,
TOutputAction extends Exclude<TInputAction, THandledAction>
>(
singleOrMultipleCreatorsAndTypes: TType | TType[] | TCreator | TCreator[],
reducer: (state: TState, action: TAction) => TState
) => [TNextNotHandledAction] extends [never]
singleOrMultipleCreatorsAndTypes: TActionCreator | TActionCreator[],
reducer: (state: TState, action: THandledAction) => TState
) => [TOutputAction] extends [never]
? Reducer<TState, TRootAction> & {
handlers: Record<
TRootAction['type'],
Expand All @@ -34,14 +26,38 @@ type CreateReducerChainApi<
}
: Reducer<TState, TRootAction> & {
handlers: Record<
Exclude<TRootAction, TNextNotHandledAction>['type'],
Exclude<TRootAction, TOutputAction>['type'],
(state: TState, action: TRootAction) => TState
>;
handleAction: CreateReducerChainApi<
TState,
TNextNotHandledAction,
TRootAction
handleAction: HandleActionChainApi<TState, TOutputAction, TRootAction>;
handleType: HandleTypeChainApi<TState, TOutputAction, TRootAction>;
};

type HandleTypeChainApi<
TState,
TInputAction extends Action,
TRootAction extends Action
> = <
TType extends TInputAction['type'],
THandledAction extends Extract<TInputAction, Action<TType>>,
TOutputAction extends Exclude<TInputAction, THandledAction>
>(
singleOrMultipleCreatorsAndTypes: TType | TType[],
reducer: (state: TState, action: THandledAction) => TState
) => [TOutputAction] extends [never]
? Reducer<TState, TRootAction> & {
handlers: Record<
TRootAction['type'],
(state: TState, action: TRootAction) => TState
>;
}
: Reducer<TState, TRootAction> & {
handlers: Record<
Exclude<TRootAction, TOutputAction>['type'],
(state: TState, action: TRootAction) => TState
>;
handleAction: HandleActionChainApi<TState, TOutputAction, TRootAction>;
handleType: HandleTypeChainApi<TState, TOutputAction, TRootAction>;
};

type GetAction<
Expand Down Expand Up @@ -83,31 +99,43 @@ export function createReducer<TState, TRootAction extends Action = RootAction>(
}
};

const handleAction = ((singleOrMultipleCreatorsAndTypes, reducer) => {
const reducerHandler = ((singleOrMultipleCreatorsAndTypes, reducer) => {
const creatorsAndTypes = Array.isArray(singleOrMultipleCreatorsAndTypes)
? singleOrMultipleCreatorsAndTypes
: [singleOrMultipleCreatorsAndTypes];

const newHandlers: typeof handlers = {};
creatorsAndTypes
.map(acOrType =>
checkValidActionCreator(acOrType)
? getType(acOrType)
: checkValidActionType(acOrType)
? acOrType
: throwInvalidActionTypeOrActionCreator()
.map(
(acOrType: TRootAction['type'] | ((...args: any[]) => TRootAction)) =>
checkValidActionCreator(acOrType)
? getType(acOrType)
: checkValidActionType(acOrType)
? acOrType
: throwInvalidActionTypeOrActionCreator()
)
.forEach(type => (newHandlers[type] = reducer));

return createReducer<TState, TRootAction>(initialState, {
...handlers,
...newHandlers,
});
}) as CreateReducerChainApi<TState, TRootAction, TRootAction>;
}) as
| HandleActionChainApi<TState, TRootAction, TRootAction>
| HandleTypeChainApi<TState, TRootAction, TRootAction>;

const chainApi = Object.assign(rootReducer, {
handlers: { ...handlers },
handleAction,
handleAction: reducerHandler as HandleActionChainApi<
TState,
TRootAction,
TRootAction
>,
handleType: reducerHandler as HandleTypeChainApi<
TState,
TRootAction,
TRootAction
>,
} as const);

return chainApi;
Expand Down
2 changes: 1 addition & 1 deletion src/type-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export type Action<TType extends TypeConstant = TypeConstant> = {
/**
* @desc Type representing Generic ActionCreator
*/
export type ActionCreator<TType extends TypeConstant> = (
export type ActionCreator<TType extends TypeConstant = TypeConstant> = (
...args: any[]
) => Action<TType>;

Expand Down

0 comments on commit ec10f89

Please sign in to comment.