Commit 044fb7d6 authored by René Jochum's avatar René Jochum

Make combineReducers typeable

parent f3410c06
import { AnyAction, ReducersMapObject } from "redux";
import Immutable from "immutable";
import {
getUnexpectedInvocationParameterMessage,
validateNextState
} from "./utilities";
import { getUnexpectedInvocationParameterMessage } from "./utilities";
export default (
export default <S extends Immutable.Map<string, any>>(
reducers: ReducersMapObject<any, AnyAction>,
getDefaultState: () => Immutable.Map<any, any> = Immutable.Map
): Function => {
getDefaultState: () => S
): ((inputState: S | undefined, action: AnyAction) => S) => {
const reducerKeys = Object.keys(reducers);
let defaultState = Immutable.Map();
const fn = getDefaultState as Function;
if (typeof getDefaultState !== "undefined") {
defaultState = fn();
}
// eslint-disable-next-line space-infix-ops
return (
inputState: Immutable.Map<any, any> = defaultState,
action: AnyAction
): Immutable.Map<any, any> => {
return (inputState: S | undefined, action: AnyAction): S => {
if (typeof inputState === "undefined") {
inputState = getDefaultState();
}
// eslint-disable-next-line no-process-env
if (process.env.NODE_ENV !== "production") {
const warningMessage = getUnexpectedInvocationParameterMessage(
const warningMessage = getUnexpectedInvocationParameterMessage<S>(
inputState,
reducers,
action
......@@ -42,7 +34,15 @@ export default (
const currentDomainState = temporaryState.get(reducerName);
const nextDomainState = reducer(currentDomainState, action);
validateNextState(nextDomainState, reducerName, action);
if (nextDomainState === undefined) {
throw new Error(
'Reducer "' +
reducerName +
'" returned undefined when handling "' +
action.type +
'" action. To ignore an action, you must explicitly return the previous state.'
);
}
temporaryState.set(reducerName, nextDomainState);
});
......
......@@ -2,8 +2,8 @@ import Immutable from "immutable";
import getStateName from "./getStateName";
import { AnyAction } from "redux";
export default (
state: Immutable.Map<any, any>,
export default <S extends Immutable.Map<string, any>>(
state: S | undefined | Object,
reducers: Object,
action: AnyAction
) => {
......@@ -29,26 +29,25 @@ export default (
);
}
const unexpectedStatePropertyNames = state
.toSeq()
.keySeq()
.toArray()
.filter(name => {
return !reducers.hasOwnProperty(name);
});
if (unexpectedStatePropertyNames.length > 0) {
return (
"Unexpected " +
(unexpectedStatePropertyNames.length === 1 ? "property" : "properties") +
' "' +
unexpectedStatePropertyNames.join('", "') +
'" found in ' +
stateName +
'. Expected to find one of the known reducer property names instead: "' +
reducerNames.join('", "') +
'". Unexpected properties will be ignored.'
if (Immutable.isMap(state)) {
let stateMap = state as Immutable.Map<string, unknown>;
const unexpectedStatePropertyNames = stateMap.filter(
(_, name) => !reducers.hasOwnProperty(name)
);
if (unexpectedStatePropertyNames.size > 0) {
return (
"Unexpected " +
(unexpectedStatePropertyNames.size === 1 ? "property" : "properties") +
' "' +
[unexpectedStatePropertyNames.keys()].join('", "') +
'" found in ' +
stateName +
'. Expected to find one of the known reducer property names instead: "' +
reducerNames.join('", "') +
'". Unexpected properties will be ignored.'
);
}
}
return null;
......
import getStateName from "./getStateName";
import getUnexpectedInvocationParameterMessage from "./getUnexpectedInvocationParameterMessage";
import validateNextState from "./validateNextState";
export {
getStateName,
getUnexpectedInvocationParameterMessage,
validateNextState
};
export { getStateName, getUnexpectedInvocationParameterMessage };
import { AnyAction } from "redux";
export default (
nextState: any,
reducerName: string,
action: AnyAction
): void => {
// eslint-disable-next-line no-undefined
if (nextState === undefined) {
throw new Error(
'Reducer "' +
reducerName +
'" returned undefined when handling "' +
action.type +
'" action. To ignore an action, you must explicitly return the previous state.'
);
}
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment