学习NgRx时报错:类型'Action'缺失'payload'属性,不满足'AddItemAction'要求
问题原因
你遇到的类型不匹配报错核心是:NgRx 内置的基础Action接口仅包含type属性,没有payload字段。你自定义的ShoppingReducer限定了只能接收ShoppingAction类型(带payload),但StoreModule.forRoot默认期望传入的reducer兼容所有基础Action类型,二者类型定义不一致导致报错。
解决方案
方案1:适配现有类式Action写法(最小改动)
无需修改原有业务逻辑,仅增加类型断言兼容NgRx的类型要求即可:
- 修改
shopping.reducer.ts文件:
// 顶部新增导入ActionReducer和基础Action import { ActionReducer, Action } from '@ngrx/store'; 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; } } // 新增这一行做类型断言,适配NgRx的类型要求 export const shoppingReducer = ShoppingReducer as ActionReducer<ShoppingItem[], Action>;
- 修改
app.module.ts导入的reducer:
// 替换原有导入为加了类型断言的版本 import { shoppingReducer } from './store/reducers/shopping.reducer' // StoreModule配置保持不变 StoreModule.forRoot({ shopping: shoppingReducer }),
方案2:使用NgRx v8+ 推荐的函数式写法(彻底解决类型问题)
目前NgRx官方已经不推荐用类定义Action,改用createAction、createReducer的写法可以自动推导类型,从根源避免该类报错,也符合当前NgRx最佳实践:
- 重写
shopping.actions.ts:
import { createAction, props } from '@ngrx/store'; import { ShoppingItem } from '../models/shopping-item.model'; export const addItem = createAction( '[SHOPPING] Add Item', props<{ payload: ShoppingItem }>() );
- 重写
shopping.reducer.ts:
import { createReducer, on } from '@ngrx/store'; import { addItem } 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 const shoppingReducer = createReducer( initialState, on(addItem, (state, { payload }) => [...state, payload]) );
app.module.ts直接导入即可,无需额外类型处理:
import { shoppingReducer } from './store/reducers/shopping.reducer' @NgModule({ imports: [ // 其他导入保持不变 StoreModule.forRoot({ shopping: shoppingReducer }), ] })
内容的提问来源于stack exchange,提问作者moses
相关产品推荐
相关产品推荐

