Connected-react-router: TypeScript definition for connectRouter excludes Action type parameter

Created on 4 Oct 2018  路  4Comments  路  Source: supasate/connected-react-router

I am defining my Action type as a discriminating union of actions:

import * as defs from '../definitions/definitions';

export enum ActionTypes {
    LOAD_USERS = "LOAD_USERS",
    LOAD_CHANNELS = "LOAD_CHANNELS"
}

export type Action = loadUsersAction | loadChannelsAction;

export interface loadUsersAction {
    type: ActionTypes.LOAD_USERS;
    users: defs.User[];
}

export interface loadChannelsAction {
    type: ActionTypes.LOAD_CHANNELS;
    channels: defs.Channel[];
}

My reducer has the following signature:

import * as defs from '../definitions/definitions';
import {Action, ActionTypes} from "../actions/actionTypes";

export const rootReducer: Reducer<stateExceptRouter, Action> = ...

However, I encounter the following type error when creating my store with connectRouter:

const store = createStore(
    connectRouter(history)(rootReducer),
    compose(
        applyMiddleware(
            routerMiddleware(history)
        ),
        (window as any).devToolsExtension ? (window as any).devToolsExtension() : (f: any) => f
    )
);

Error: property 'channels' is missing from AnyAction

This stems from the type definition for connectRouter:

  export function connectRouter(history: History)
    : <S>(reducer: Reducer<S>) => Reducer<S>

This should take an optional second type parameter so I can provide an Action type and avoid this issue.

Most helpful comment

Released in 5.0.0! (Beware of the breaking change. Please see the release note https://github.com/supasate/connected-react-router/releases/tag/v5.0.0)

All 4 comments

As a follow up, I also noticed an additional issue with the TypeScript definitions. I found that when I define my Action type as follows:

import {RouterAction} from "connected-react-router";

export type Action = RouterAction | loadUsersAction | loadChannelsAction;

I start seeing type errors in my reducer which stems from the fact that it isn't able to narrow down the union type after checking the type field on the action. This is due to the fact that the RouterAction interface is defined as:

declare module 'connected-react-router' {

  export const CALL_HISTORY_METHOD: string

  export interface RouterAction {
    type: typeof CALL_HISTORY_METHOD;
    payload: LocationActionPayload;
  }

}

In this interface, the 'type' field will always just have the generic string type, so it breaks the discriminated union I am using for my Action type.

Yeah, this is not good for me as well. Since type is string in RouterAction all of my overloads keeps pointing to RouterAction instead of my Actions in Typescript.

This code is no go since type is typeof string

    type Actions = AddAction & RemoveAction

    function dispatch(action: Actions)
    function dispatch(action: RouterAction)
    function dispatch(action) {

    }

whenever I'm using dispatch({ type: ActionType.Add}) it thinks action is a RouterAction. ActionType.Add is a enum of string and a part of the definition for AddAction.

I would really like type to be a union of all possible values, eg:

 export interface LocationChangeAction {
    type: LOCATION_CHANGE;
    payload: RouterState;
  }

  export type LOCATION_CHANGE = '@@router/LOCATION_CHANGE'
  export type CALL_HISTORY_METHOD = '@@router/CALL_HISTORY_METHOD'

  type ActionTypes = LOCATION_CHANGE & CALL_HISTORY_METHOD

  export interface RouterAction {
    type: ActionTypes
    payload: LocationActionPayload;
  }

In redux, type is never a variable string, it's a constant of type that is read-only, eg LOCATION_CHANGE. So the type here is really '@@router/LOCATION_CHANGE', not a string.

I can see that PR #149 will solve this issue. When will this be merged @supasate ?

Released in 5.0.0! (Beware of the breaking change. Please see the release note https://github.com/supasate/connected-react-router/releases/tag/v5.0.0)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

pachuka picture pachuka  路  4Comments

dcs3spp picture dcs3spp  路  3Comments

slightlytyler picture slightlytyler  路  5Comments

jhwheeler picture jhwheeler  路  3Comments

austsinovich picture austsinovich  路  4Comments