“Action”类型中缺少属性“payload”,但“AddItemAction”类型中需要属性“payload”

mos*_*ses 9 ngrx angular

我一直在尝试创建一个示例应用程序来学习 ngrx,我的应用程序只有一个“操作”ADD_ITEM,并且它有一个减速器函数,该函数根据操作类型对状态进行操作。

购物.actions.ts

 import { Action } from '@ngrx/store'
 import {ShoppingItem} from '../models/shopping-item.model'

 export enum ShoppingActionTypes{
     ADD_ITEM = '[SHOPPING] Add Item'
 }

 export class AddItemAction implements Action {
     readonly type = ShoppingActionTypes.ADD_ITEM

     constructor(public payload: ShoppingItem) { }
 }

 export type ShoppingAction = AddItemAction;
Run Code Online (Sandbox Code Playgroud)

购物.reducer.ts

//   import { ShoppingAction, ShoppingActionTypes } from "../actions/shopping-actions";
  import { ShoppingActionTypes, ShoppingAction } from "../actions/shopping.actions";

  import { ShoppingItem } from '../models/shopping-item.model';


const initialState: Array<ShoppingItem> = [
  {
    id: "1775935f-36fd-467e-a667-09f95b917f6d",
    name: 'Diet Coke',
  }
];

export function ShoppingReducer(state: Array<ShoppingItem> = initialState, action: ShoppingAction) {
  switch (action.type) {
    case ShoppingActionTypes.ADD_ITEM:
      return [...state, action.payload];

    default:
      return state;
  }
}
Run Code Online (Sandbox Code Playgroud)

问题出现在app.module.ts中

应用程序模块.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { StoreModule } from '@ngrx/store';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { ShoppingReducer } from './store/reducers/shopping.reducer'
@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    StoreModule.forRoot({
      shopping: ShoppingReducer
    }),
    
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
Run Code Online (Sandbox Code Playgroud)

错误

Error: src/app/app.module.ts:16:7 - error TS2322: Type '(state: ShoppingItem[] | undefined, action: AddItemAction) => ShoppingItem[]' is not assignable to type 'ActionReducer<ShoppingItem[], Action>'.
  Types of parameters 'action' and 'action' are incompatible.
    Property 'payload' is missing in type 'Action' but required in type 'AddItemAction'.

16       shopping: ShoppingReducer
         ~~~~~~~~

  src/app/store/actions/shopping.actions.ts:11:18
    11      constructor(public payload: ShoppingItem) { }
                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    'payload' is declared here.
Run Code Online (Sandbox Code Playgroud)

谢谢!

Rud*_*dez 10

您的 Angular/ngrx 版本可能较新。在最新版本的 NgRx(截至 2021 年 7 月,目前为 v12.2.0)中,有用于创建操作和减速器的工厂方法。

使用createAction 的操作:

import { createAction, props } from "@ngrx/store";
import { ShoppingItem } from "../models/shopping-item.model";

export const AddItemAction = createAction(
  '[SHOPPING] Add Item',
  props<{payload: ShoppingItem}>()
);
Run Code Online (Sandbox Code Playgroud)

创建Reducer

import { Action, createReducer, on } from '@ngrx/store';
import { AddItemAction } from '../actions/shopping.actions';
import { ShoppingItem } from '../models/shopping-item.model';

const reducer = createReducer(
   initialState,
   on(AddItemAction, (state, action) => {
      return [...state, action.payload]
   })
);

export function ShoppingReducer(state: Array<ShoppingItem> | undefined, action: Action) {
  return reducer(state, action);
}
Run Code Online (Sandbox Code Playgroud)


Oll*_*lli 6

只需将您的减速器的签名从更改(..., ShoppingAction)(..., Action)

export function ShoppingReducer(state: Array<ShoppingItem> = initialState, action: Action) {
  switch (action.type) {
    case ShoppingActionTypes.ADD_ITEM:
      return [...state, (action as ShoppingAction).payload];

    default:
      return state;
  }
}
...
Run Code Online (Sandbox Code Playgroud)

似乎StoreModule.forRoot(...)期待这个签名。

一个小小的副作用是,如果代码片段的第 4 行中存在类型,我们需要将 强制转换action为 a 。ShoppingActionShoppingActionTypes.ADD_ITEM