I am new to angular. Here I using ngrx to manage a state in my angular app. But when I'm compiling I got the following error. It says that 'Types of parameters 'action' and 'action' are incompatible'. I want to know the reason for this and how to solve this?
Error: src/app/shopping-list/store/shoppingList.actions.ts:9:5 - error TS2564: Property 'payload' has no initializer and is not definitely assigned in the constructor.
9 payload: Ingredient;
~~~~~~~
src/app/app.module.ts:25:27 - error TS2322: Type '(state: { ingredients: Ingredient[]; } | undefined, action: AddIngredient) => { ingredients: Ingredient[]; }' is not assignable to type 'ActionReducer<{ ingredients: Ingredient[]; }, Action>'.
Types of parameters 'action' and 'action' are incompatible.
Property 'payload' is missing in type 'Action' but required in type 'AddIngredient'.
25 StoreModule.forRoot({ shoppingList: shoppingListReducer }),
~~~~~~~~~~~~
src/app/shopping-list/store/shoppingList.actions.ts:9:5
9 payload: Ingredient;
~~~~~~~
'payload' is declared here.
This is my shoppingList.actions.ts file.
import { Action } from '@ngrx/store'
import { Ingredient } from '../../shared/ingredient.model';
export const ADD_INGREDIENT = 'ADD_INGREDIENT';
export class AddIngredient implements Action {
readonly type = ADD_INGREDIENT;
payload: Ingredient;
}
This is the shoppingList.reducer.ts file.
import { Ingredient } from "src/app/shared/ingredient.model";
import * as shoppingListActions from './shoppingList.actions';
const intialState = {
ingredients: [
new Ingredient("Apples", 3),
new Ingredient("Tomatoes", 4)
]
}
export function shoppingListReducer(state = intialState, action: shoppingListActions.AddIngredient) {
switch (action.type) {
case shoppingListActions.ADD_INGREDIENT:
return {
...state,
ingredients: [...state.ingredients, action.payload]
}
default:
return state;
}
}
Here is my app.module.ts file.
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRouting } from './app-routing.module';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';
import { StoreModule } from '@ngrx/store';
import { AppComponent } from './app.component';
import { HeaderComponent } from './header/header.component';
import { SharedModule } from './shared/shared.module';
import { CoreModule } from './core.module';
import { shoppingListReducer } from './shopping-list/store/shoppingLis.reducer';
@NgModule({
declarations: [
AppComponent,
HeaderComponent,
],
imports: [
BrowserModule,
FormsModule,
ReactiveFormsModule,
HttpClientModule,
StoreModule.forRoot({ shoppingList: shoppingListReducer }),
AppRouting,
SharedModule,
CoreModule,
],
bootstrap: [AppComponent]
})
export class AppModule { }
Your problem is because of signature issue,
Method StoreModule.forRoot<unknown, Action>(reducers: ActionReducerMap<unknown, Action>)
Technically you are passing a correct parameter but still it is saying that your Action object parameter contains a field call payload which is not present in Action parameter of ActionReducerMap<unknown, Action>. Technically it should not be an error as you have already inherited Action to your action class
class AddIngredient implements Action{
but unfortunately it is clear that Action in ActionReducerMap<unknown, Action> is not from '@ngrx/store' or they are not same, and therefore giving the compilation error.
As you don't have any other option, you have to fix it like below:-
First create your State like below in your shopping-list.reducer.ts
Also modify your reducer method like below:-
Now create a file call index.ts ( in the same location of reducer file - you can provide a different name as well) like below under your action folder
Now import this reducers to your app.module.ts
and modify your code like below
Also try to avoid declaration of variable like below.
better use constructor and modify your code like below:-
Hope this will fix your issue.