Angular 12 NgRx状态管理在app.module注册reducer报错如何解决
问题原因
你使用的新版NgRx要求传入StoreModule.forRoot的reducer符合ActionReducer<State, Action>类型定义。你现有代码中自定义的reducer仅接收你声明的Actions联合类型(所有实例都携带payload属性),和NgRx内置的基础Action类型(仅携带type属性)不兼容,因此触发类型校验错误。
解决方案
方案1:适配现有类式Action写法
仅需修改reducer文件的类型声明,兼容NgRx内置类型即可,无需调整其他代码:
import { Action, ActionReducer } from '@ngrx/store' import { Tutorial } from '../_models/tutorial.model'; import * as TutorialActions from './../_actions/tutorial.actions' const initialState: Tutorial = { name: 'Initial Tutorial', url: 'http://google.com' } // 明确标注reducer类型,action参数兼容内置Action和自定义Actions类型 export const reducer: ActionReducer<Tutorial[], Action> = (state: Tutorial[] = [initialState], action: Action | TutorialActions.Actions) => { switch(action.type) { case TutorialActions.ADD_TUTORIAL: // 进入对应case后Typescript会自动收窄类型,可安全获取payload return [...state, (action as TutorialActions.AddTutorial).payload]; case TutorialActions.REMOVE_TUTORIAL: // 后续实现删除逻辑可直接用以下写法 return state.filter((_, index) => index !== (action as TutorialActions.RemoveTutorial).payload); default: return state; } }
方案2:改用NgRx官方推荐的函数式写法(更简洁,无类型冲突)
新版NgRx更推荐使用createAction、createReducer的函数式语法,无需手动声明类和联合类型,自动完成类型推导,不会出现上述类型错误:
- 替换Action文件代码:
import { createAction, props } from '@ngrx/store' import { Tutorial } from '../_models/tutorial.model' export const addTutorial = createAction('[TUTORIAL] Add', props<{ payload: Tutorial }>()); export const removeTutorial = createAction('[TUTORIAL] Remove', props<{ payload: number }>());
- 替换Reducer文件代码:
import { createReducer, on } from '@ngrx/store' import { Tutorial } from '../_models/tutorial.model'; import { addTutorial, removeTutorial } from './../_actions/tutorial.actions' const initialState: Tutorial[] = [ { name: 'Initial Tutorial', url: 'http://google.com' } ] export const reducer = createReducer( initialState, on(addTutorial, (state, { payload }) => [...state, payload]), on(removeTutorial, (state, { payload }) => state.filter((_, index) => index !== payload)) )
两种方案任选其一修改完成后,app.module.ts中的代码无需调整,报错即可消失。
内容的提问来源于stack exchange,提问作者mnu-nasir
相关产品推荐
相关产品推荐

