Susitha Ravinda Senarath
Susitha Ravinda Senarath

Reputation: 1678

ReactJs, Redux with typescript. Typed combineReducers error

React app has multiple redux slices and reducers have a signature like following

User reducer:

export const user = (
  state: UserState = initialState,
  action: UserAction
): UserState => {
  .....
};

Document reducer:

export const document = (
  state: DocumentState = initialState,
  action: DocumentAction
): DocumentState => {
  ....
};

Action and State types are integrate as follows

export type StoreAction = UserAction | DocumentAction;

export type StoreState = {
  user: UserState;
  document: DocumentState;
};

Then creating the root reducer like this

const rootReducer = combineReducers<StoreState, StoreAction>({
  user,
  document
});

This gives erros at each passed reducer

(property) document: Reducer<DocumentState, any>
Type '(state: DocumentState | undefined, action: DocumentAction) => DocumentState' is not assignable to type 'Reducer<DocumentState, StoreAction>'.
  Types of parameters 'action' and 'action' are incompatible.
    Type 'StoreAction' is not assignable to type 'DocumentAction'.
      Type 'SetUsers' is not assignable to type 'DocumentAction'.
        Type 'SetUsers' is not assignable to type 'ResetDocuments'.
          Types of property 'type' are incompatible.
            Type '"SET_USERS"' is not assignable to type '"RESET_DOCUMENTS"'.ts(2322)
types.ts(9, 3): The expected type comes from property 'document' which is declared here on type 'ReducersMapObject<StoreState, StoreAction>'

and

(property) user: Reducer<UserState, any>
Type '(state: UserState | undefined, action: UserAction) => UserState' is not assignable to type 'Reducer<UserState, StoreAction>'.
  Types of parameters 'action' and 'action' are incompatible.
    Type 'StoreAction' is not assignable to type 'UserAction'.
      Type 'SetDocuments' is not assignable to type 'UserAction'.
        Type 'SetDocuments' is not assignable to type 'ResetUsers'.
          Types of property 'type' are incompatible.
            Type '"SET_DOCUMENTS"' is not assignable to type '"RESET_USERS"'.ts(2322)
types.ts(8, 3): The expected type comes from property 'user' which is declared here on type 'ReducersMapObject<StoreState, StoreAction>'

I'm intended to use the combinedReducer with signature

export function combineReducers<S, A extends Action = AnyAction>(
  reducers: ReducersMapObject<S, A>
): Reducer<CombinedState<S>, A>

type of ReducersMapObjects seems to be the issue

export type ReducersMapObject<S = any, A extends Action = Action> = {
  [K in keyof S]: Reducer<S[K], A>
}

Seems like each reducer is suppose to return the StoreAction. But that cannot be correct or am I doing something wrong here.

Complete sample here

Update with first answer.

export type StoreAction = UserAction & DocumentAction;

This works. But when I apply this to my actual app which as more than 10 slices intersection of all types.

export type StoreAction = Actoin1 & Action2 & ... & Action10;

This seems too complex because i get error.

Expression produces a union type that is too complex to represent.ts

Upvotes: 1

Views: 571

Answers (1)

underscore
underscore

Reputation: 6887

This is caused by OR operator. You need AND

Change this to

export type StoreAction = UserAction | DocumentAction;

Into

export type StoreAction = UserAction & DocumentAction;

Updated Answer

You can use TypeScript tuple

export type StoreAction = [Actoin1, Action2, ..., Action10]

Upvotes: 2

Related Questions