Open kazamov opened 4 years ago
Question: what shape are your actions such that they aren't compatible with redux's AnyAction interface? The AnyAction interface only requires a type
field and lets any other assigned field be any
.
I am using 'flux-standard-action' library typings: FSAAuto and ErrorFSAAuto. Link to typings file https://github.com/redux-utilities/flux-standard-action/blob/master/src/index.d.ts.
I have a reducer
export function appReducer(state: AppState = initialAppState, action: AppActions): AppState {...}
Where AppActions is
export type AppActions = FSAAuto<AppActionTypes.REQUEST_APP_METADATA, AppMetadataPayload> | FSAAuto<AppActionTypes.REQUEST_APP_METADATA_SUCCEED, App> | ErrorFSAAuto<AppActionTypes.REQUEST_APP_METADATA_FAILED>
In my module
export const AppModule: ISagaModule<AppAwareState> = { id: 'appModule', reducerMap: { appModule: appReducer, }, // TODO: fix typing issue sagas: [rootSaga], };
I see a TS error:
(property) IModule
Type '{ appModule: (state: AppState | undefined, action: AppActions) => AppState; }' is not assignable to type 'ReducersMapObject<AppAwareState, AnyAction>'.
Types of property 'appModule' are incompatible.
Type '(state: AppState | undefined, action: AppActions) => AppState' is not assignable to type 'Reducer<AppState, AnyAction>'.
Types of parameters 'action' and 'action' are incompatible.
Type 'AnyAction' is not assignable to type 'AppActions'.
Type 'AnyAction' is not assignable to type 'ErrorFluxStandardActionWithPayload<AppActionTypes.REQUEST_APP_METADATA_FAILED, Error, undefined>'.
Property 'error' is missing in type 'AnyAction' but required in type 'ErrorFluxStandardAction<AppActionTypes.REQUEST_APP_METADATA_FAILED, Error, undefined>'.ts(2322)
index.d.ts(47, 3): 'error' is declared here.
Contracts.d.ts(13, 5): The expected type comes from property 'reducerMap' which is declared here on type 'ISagaModule
Thus it would be nice to have possibility to set own action types. By default it can be set to AnyAction
@kazamov did you figure this out? If you have a repo where I can see the problem, that may better help me understand your problem.
I am encountering the same problem. I am trying to use connected-react-router and getting the following error:
TypeScript error in /myapp/src/app/store/module.ts(13,3): Type '{ router: Reducer<RouterState
, LocationChangeAction >; }' is not assignable to type 'ReducersMapObject<AppModuleState, AnyAction>'. Types of property 'router' are incompatible. Type 'Reducer<RouterState , LocationChangeAction >' is not assignable to type 'Reducer<RouterState , AnyAction>'. Types of parameters 'action' and 'action' are incompatible. Type 'AnyAction' is not assignable to type 'LocationChangeAction '. TS2322
Here is my code:
import {ISagaModule} from 'redux-dynamic-modules-saga'
import {connectRouter, routerMiddleware, RouterState} from 'connected-react-router'
import history from 'utils/history'
const routerReducer = connectRouter(history)
interface AppModuleState {
router: RouterState,
}
const AppModule: ISagaModule<AppModuleState> = {
id: 'app',
reducerMap: {
router: routerReducer,
},
middlewares: [
routerMiddleware(history),
],
sagas: [],
}
export default AppModule
I believe this might be because of strict contravariance and the way that RouterState
is defined by connected-react-router
. I was able to workaround it by adding the following assertion:
import {Reducer} from 'redux'
.
.
.
const routerReducer = connectRouter(history) as Reducer<RouterState>
I don't know if the best way to handle this is to change the signature of IModule
to accept a generic action type, or to just assign manually as I've done above. Just thought this might be helpful to anyone else who encounters this issue.
Hi @bloomdido.
I have found a workaround for this issue. If cast the type of "reducerMap" property to ReducersMapObject
export const RoleModule: ISagaModule<RoleAwareState> = {
id: 'roleModule',
reducerMap: {
roleModule: roleReducer,
} as ReducersMapObject<RoleAwareState>,
sagas: [rootSaga],
};
@kazamov Yeah, I think both of our solutions are about getting around Typescript's strict contravariance for callbacks.
From what I understand, the issue is that any action can always be an AnyAction
, but an AnyAction
cannot always be any action.
From what I understand, the issue is that any action can always be an
AnyAction
, but anAnyAction
cannot always be any action.
@bloomdido , This seems to be the same issue I am now encountering with putting a ThunkAction
in the initialActions
part of the module. Any suggestions on resolving this? I have not been able to find a way to eliminate this problem.
export const fetchToplineData = (): ThunkAction<any, any, any, AnyAction> => {
return (dispatch, getState) => {
const mockData = [{ a: 1, b: 2, c: 3, s: getState() }];
dispatch(toplineDataAvailable(mockData));
};
};
export function getToplineModule(): IModule<any> {
return {
// Unique id of the module
id: "topline",
// Maps the Store key to the reducer
reducerMap: {
topline: toplineReducer,
},
initialActions: [fetchToplineData()], // this line errors
finalActions: [],
};
}
Error Produced
TS2741: Property 'type' is missing in type 'ThunkAction<any, any, any, AnyAction>' but required in type 'AnyAction'.
From what I understand, the issue is that any action can always be an
AnyAction
, but anAnyAction
cannot always be any action.@bloomdido , This seems to be the same issue I am now encountering with putting a
ThunkAction
in theinitialActions
part of the module. Any suggestions on resolving this? I have not been able to find a way to eliminate this problem.export const fetchToplineData = (): ThunkAction<any, any, any, AnyAction> => { return (dispatch, getState) => { const mockData = [{ a: 1, b: 2, c: 3, s: getState() }]; dispatch(toplineDataAvailable(mockData)); }; };
export function getToplineModule(): IModule<any> { return { // Unique id of the module id: "topline", // Maps the Store key to the reducer reducerMap: { topline: toplineReducer, }, initialActions: [fetchToplineData()], // this line errors finalActions: [], }; }
Error Produced
TS2741: Property 'type' is missing in type 'ThunkAction<any, any, any, AnyAction>' but required in type 'AnyAction'.
Hi @forgo, I described the workaround above, you should cast 'reducerMap' to proper type
Hi @kazamov , just to be clear, my error is on initialActions
not the reducerMap
. Not sure if that is related. I had already tried your example above casting reducerMap
as ReducersMapObject<any>
and ReducersMapObject<any, any>
and still have this error before posting here.
Please update IModule interface, so it will be possible to set Action type, e.g.
export interface IModule<State, Action = AnyAction> { /**