You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 07:45:32