NGRX 4 Router Store类型错误:RouterNavigationAction payload不匹配
这个问题的核心是默认的RouterNavigationAction泛型类型是RouterStateSnapshot,而你的自定义序列化器已经把路由状态转换成了RouterStateUrl,但编译器还在沿用默认类型判断,所以会出现类型不兼容的报错。不用绕过类型检查,我们可以通过显式指定泛型参数来解决。
步骤1:修改辅助方法的类型定义
首先,确保你导入的RouterNavigationAction支持泛型,然后给它指定你的自定义类型RouterStateUrl,这样编译器就能识别payload.routerState的实际类型:
import { RouterNavigationAction } from '@ngrx/router-store'; import { RouterStateUrl } from './your-path-to-router-state-url'; // 替换成你的实际路径 export const firstSegment = (r: RouterNavigationAction<RouterStateUrl>): RouterStateUrl => { // 这里不需要强制类型转换了,类型已经完全匹配 return r.payload.routerState; };
步骤2:在Effect中使用正确的Action类型
在你的Effect里,处理ROUTER_NAVIGATION动作时,也要显式指定泛型,确保数据流的类型一致:
import { Actions, Effect, ofType } from '@ngrx/effects'; import { RouterNavigationAction, ROUTER_NAVIGATION } from '@ngrx/router-store'; import { map } from 'rxjs/operators'; // ...其他导入和类定义 @Effect() routeChangeEffect$ = this.actions$.pipe( // 显式指定动作的泛型为RouterStateUrl ofType<RouterNavigationAction<RouterStateUrl>>(ROUTER_NAVIGATION), map(firstSegment), // 后续你的业务逻辑 );
验证自定义序列化器的配置
确保你已经正确注册了自定义序列化器,这是运行时状态能转换成RouterStateUrl的基础:
import { RouterStateSerializer } from '@ngrx/router-store'; import { RouterStateSnapshot } from '@angular/router'; import { Injectable } from '@angular/core'; import { RouterStateUrl } from './your-path-to-router-state-url'; @Injectable() export class CustomRouterSerializer implements RouterStateSerializer<RouterStateUrl> { serialize(routerState: RouterStateSnapshot): RouterStateUrl { let route = routerState.root; // 遍历到最底层的路由节点(根据你的业务需求调整) while (route.firstChild) { route = route.firstChild; } const { url, root: { queryParams } } = routerState; const { params } = route; // 返回符合RouterStateUrl类型的对象 return { url, params, queryParams }; } }
然后在AppModule中注册:
import { StoreRouterConnectingModule } from '@ngrx/router-store'; import { CustomRouterSerializer } from './your-path-to-serializer'; @NgModule({ imports: [ // ...其他模块 StoreRouterConnectingModule.forRoot({ serializer: CustomRouterSerializer }) ], providers: [CustomRouterSerializer] }) export class AppModule {}
这样修改后,编译器就能正确识别路由状态的类型,既不需要用any绕过检查,也能保证类型安全。
内容的提问来源于stack exchange,提问作者Jason
相关产品推荐
相关产品推荐

