export interface UserActions extends Action { type: UserKind; payload: UserPayload; }
..TypeScript will raise an error on combineReducers:
To fix the compilation error, make the Redux action property be optional:
export interface UserActions extends Action { type: UserKind; payload?: UserPayload; }
Result:
However, TypeScript won't be able to catch missed properties, it won't raise an error that we didn't pass the payload property on User 6:
To fix that, remove the optional indicator on Redux action:
export interface UserActions extends Action { type: UserKind; payload: UserPayload; }
Result, TypeScript is now able to catch missed properties:
However, we are back to this error on combineReducers:
To comply with combineReducers requirement of Reducer actions containing just a type property only, create another interface that has optional properties (e.g., payload), and use that for the Redux reducer's action parameter (UserActionsNoPayload). And then on UserActions, inherit UserActionsNoPayload from UserActions:
Now, no more combineReducers compilation error, and the compiler is still able to catch missed properties:
Here are the TypeScript definitions for the routeToUser:
export interface StateProps { user: Dto.Client.User; component: Component; counter: Dto.Client.Counter; } export interface ActionProps { routeToUser: UserDispatcher; doCounter: CounterDispatcher; } interface Props extends StateProps, ActionProps { } export type Dispatcher = (action: UserActions | CounterActions) => void; export type UserDispatcher = (action: UserActions) => void; export type CounterDispatcher = (action: CounterActions) => void; export default class ReduxFirstRouterApp extends React.Component<Props, {}> {
And here is how are the states and dispatchers are mapped as properties to a component via Redux's connect:
const mapStateToProps = ({user, component, counter}: StateProps) => ({user, component, counter}); const mapDispatchToProps = (dispatch: Dispatcher): ActionProps => ({ routeToUser: (action: UserActions) => dispatch(action), doCounter: (action: CounterActions) => dispatch(action) }); this.AppContainer = connect(mapStateToProps, mapDispatchToProps)(ReduxFirstRouterApp);
Happy Coding!
P.S.
At first, I tried creating UserActions with complete properties, and then made UserActionsNoPayload inherits UserActions and define payload as optional on UserActionsNoPayload; however, it's a compiler error: