RTK Query的updateQueryData无法更新状态?类型不兼容问题求助
问题:RTK updateQueryData push 失效 + TypeScript 类型错误
我用RTK发起请求,想让服务器返回的结果覆盖原有状态(替换原数组),但用updateQueryData结合push方法时完全没效果,还报类型错误:Argument of type 'RowType' is not assignable to parameter of type never。刚学TypeScript,估计是类型定义出问题了,相关代码如下:
类型定义代码
export interface RowListItemLevel1 { children: RowListItemLevel2[] | [], //| RowType[], id: number, parent: number, price: number, quantity: number, title: string, type: string, unit: string, unitPrice: number, } export interface RowListItemLevel2 { children: RowListItemLevel1[] | [],//| RowType[], id: number, parent: number, price: number, quantity: number, title: string, type: string, unit: string, unitPrice: number, }
RTK Mutation代码
createRow: build.mutation<RowBaseResponse, RowAddRequest>({ query: ({ id:calculationId, ...body } ) =>{ return { url: `/calculation/${calculationId}/row/add`, method: 'POST', body, }}, async onQueryStarted({id:calculationId, ...patch }, { dispatch, queryFulfilled }) { try { const { data: createRow } = await queryFulfilled dispatch( calculationsApi.util.updateQueryData('getRowsList', {id:calculationId},(draft) => { function changedCreateRow(arr:RowListItemLevel1[]){ arr.forEach((elem: RowListItemLevel1)=> { if (elem.id === createRow.current.parent) { elem.children.push(createRow.current) } return changedCreateRow(elem.children); }) } changedCreateRow(draft.data) }) ) } catch {} }, // invalidatesTags: ['CreateRow'], }),
解决步骤
1. 修复类型定义的核心问题
你的类型定义里children字段写了[](空数组字面量),TypeScript会把它推断为never[],这就是never类型错误的直接原因。另外两个接口互相引用,也会导致类型推断异常。改成统一基类+明确数组类型:
// 提取公共字段作为基类,避免重复定义 type RowListItemBase = { id: number, parent: number, price: number, quantity: number, title: string, type: string, unit: string, unitPrice: number, } export interface RowListItemLevel1 extends RowListItemBase { children: RowListItemLevel2[] } export interface RowListItemLevel2 extends RowListItemBase { children: RowListItemLevel1[] }
2. 修正递归逻辑的类型不匹配与无限递归问题
原来的递归函数把RowListItemLevel2[]传入要求RowListItemLevel1[]的函数,导致类型错误,同时没有终止条件会引发无限递归。改成区分层级的遍历:
async onQueryStarted({ id: calculationId, ...patch }, { dispatch, queryFulfilled }) { try { const { data: createRow } = await queryFulfilled; dispatch( calculationsApi.util.updateQueryData('getRowsList', { id: calculationId }, (draft) => { // 遍历Level1节点 const traverseLevel1 = (arr: RowListItemLevel1[]) => { arr.forEach(elem => { if (elem.id === createRow.current.parent) { // 根据createRow.current的实际类型做断言,这里假设是Level2 elem.children.push(createRow.current as RowListItemLevel2); } // 递归遍历当前节点的Level2子节点 traverseLevel2(elem.children); }); }; // 遍历Level2节点 const traverseLevel2 = (arr: RowListItemLevel2[]) => { arr.forEach(elem => { if (elem.id === createRow.current.parent) { elem.children.push(createRow.current as RowListItemLevel1); } // 递归遍历当前节点的Level1子节点 traverseLevel1(elem.children); }); }; traverseLevel1(draft.data); }) ); } catch {} }
如果createRow.current是自定义的RowType,需要确保RowType与RowListItemLevel1/RowListItemLevel2结构兼容,或者通过type字段判断层级后再做断言。
3. 确认查询返回类型匹配
检查getRowsList查询的返回类型是否为RowListItemLevel1[],如果不匹配,需要修正该查询的类型定义,或者在updateQueryData中对draft.data做类型断言:draft.data as RowListItemLevel1[]。
内容的提问来源于stack exchange,提问作者Daniel West
相关产品推荐
相关产品推荐

