问题
Below is simplified version of my Angular 5 application. I have a reducer, which I want to register in my root module. In LINE A I am getting following error:
ERROR in src/app/store/app.reducers.ts(7,14): error TS2322: Type '{ post: (state: State, action: Action) => void; }' is not assignable to type 'ActionReducerMap<AppState, Action>'.
Types of property 'post' are incompatible.
Type '(state: State, action: Action) => void' is not assignable to type 'ActionReducer<State, Action>'.
Type 'void' is not assignable to type 'State'.
app.module.ts : Root module
imports: [
...
StoreModule.forRoot(reducers)
],
store/app.reducers.ts : inside Global store
import {ActionReducerMap} from "@ngrx/store";
import * as fromPost from "../postDir/store/post.reducers";
export interface AppState {
post:fromPost.State
}
export const reducers: ActionReducerMap<AppState> = { //=======LINE A ======
post:fromPost.postReducer
};
postDir/store/post.reducers.ts :inside local store
export interface State{
query:string
posts:Post[]
}
const initialPostState: State = {
query:"initial",
posts:[]
};
export function postReducer(state = initialPostState, action:postActions.PostActions){}
Code works fine if I replace <AppState>
in LINE A with <any>
Did anyone else face the similar issue? I tried to google but could not find anything significant.
回答1:
Your error message says that property post has the wrong method signature. It is (state: State, action: Action) => void
, but should be (state: State, action: Action) => State
.
In post.reducers.ts your reducer needs to return the state that is passed into it like this:
export function postReducer(state = initialPostState, action:Action) {
return state;
};
The return type is being implicitly inferred from what you are, or in this case aren't, returning.
You could explicitly state the return type with ...): State {...
but you should still return the state.
回答2:
I got a similar situation, and after a lot of time, checking my code, I found a missing property return in the switch case actions in the reducer.
Make sure you load your previous state with spread operator ...state
so you avoid a lot of problems hard to find. In my case I returned all properties but one without first load the previous state. Got the TS2322 error and spent hours to fix and understand what happens.
Taking your code as example:
export function postReducer(state = initialPostState, action:postActions.PostActions){
// here you must return the state after an action
switch (action.type){
case postActions.ACTION_EXAMPLE:
return {
...state, someProperty: action.payload // here you load your previous state and change just that one you want
}
case postActions.ACTION_02_EXAMPLE:
return {
...state, someProperty: action.payload // here you load your previous state and change just that one you want
}
default:
return { ...state}
}
}
Hope it helps!
回答3:
Answering if someone stumbles upon the same mistake I did. I had this issue using @ngrx/entity
when I wanted to reset the state to the initial state on a specific action. I had
I had
on(actions.resetState, () => adapter.getInitialState())
when I should have had the extra properties included like
on(actions.resetState, () => adapter.getInitialState({ foo: 'bar' }))
来源:https://stackoverflow.com/questions/48706362/getting-error-while-registering-reducers-using-actionreducermap-not-assignable