React Query中'isSuccess'属性类型不兼容问题排查与解决
React Query UseQueryResult 与自定义 QueryResult 类型不兼容问题
错误原因
核心问题是自定义的QueryResult联合类型未覆盖UseQueryResult的全部状态分支:
- React Query 的
UseQueryResult包含多组状态组合:初始加载(isPending: true)、加载成功(isSuccess: true)、加载失败(isError: true),以及重新获取数据时的混合状态(如isSuccess: true同时isPending: true)。 - 你的
QueryResult仅定义了两种状态:加载中(isPending: true+isSuccess: false)、加载成功(isSuccess: true+isPending: false),完全遗漏了错误状态(isError: true)及其他合法状态组合。 - TypeScript 检测到
UseQueryResult中存在QueryObserverRefetchErrorResult这类分支(比如重新获取失败时,isSuccess: false但isPending: false、isError: true),无法匹配QueryResult的任何分支,因此抛出isSuccess类型不兼容的错误。
解决方法
由于架构限制无法直接使用UseQueryResult,你需要扩展自定义QueryResult覆盖所有必要状态,或通过适配函数将UseQueryResult安全转换为QueryResult类型。
方法1:完善QueryResult类型,覆盖全状态分支
修改QueryResult,添加错误状态和重新加载的混合状态分支,对齐UseQueryResult的状态覆盖范围:
import { get } from "lodash-es" import { useQuery } from '@tanstack/react-query' // 扩展QueryResult,覆盖错误状态与重新加载状态 type QueryResult<TData extends object> = | { isSuccess: false isPending: true isError: false data: undefined } | { isSuccess: true isPending: false isError: false data: TData } | { isSuccess: true isPending: true isError: false data: TData } | { isSuccess: false isPending: false isError: true data: undefined error: Error } class DataListManager<TData extends object, TPath extends keyof TData> { constructor( private readonly _query: QueryResult<TData>, private readonly _path: TPath, ) {} get query() { const items = get(this._query.data, this._path) ?? [] return { ...this._query, data: { items, }, } } } type Transaction = {} function useTransactionsListManager() { const query = useQuery({ async queryFn() { const data = await new Promise<{transactions: Array<Transaction>}>(resolve => { resolve({ transactions: [] }) }) return data }, queryKey: ['transactions'] }) // 类型匹配,无报错 return new DataListManager(query as QueryResult<{ transactions: Transaction[] }>, "transactions") }
方法2:创建适配函数,安全转换类型
若不想修改QueryResult结构,可编写适配函数将UseQueryResult的状态映射到自定义QueryResult分支:
import { get } from "lodash-es" import { useQuery, UseQueryResult } from '@tanstack/react-query' type QueryResult<TData extends object> = | { isSuccess: false isPending: true isError: false data: undefined } | { isSuccess: true isPending: false isError: false data: TData } // 适配函数:将UseQueryResult转换为QueryResult function adaptToQueryResult<TData extends object>( query: UseQueryResult<TData, Error> ): QueryResult<TData> { if (query.isSuccess && !query.isPending) { return { isSuccess: true, isPending: false, isError: false, data: query.data, } } if (query.isPending && !query.isError) { return { isSuccess: false, isPending: true, isError: false, data: undefined, } } // 错误状态可根据业务需求映射为兼容分支,此处示例映射为非成功非加载状态 return { isSuccess: false, isPending: false, isError: false, data: undefined, } } class DataListManager<TData extends object, TPath extends keyof TData> { constructor( private readonly _query: QueryResult<TData>, private readonly _path: TPath, ) {} get query() { const items = get(this._query.data, this._path) ?? [] return { ...this._query, data: { items, }, } } } type Transaction = {} function useTransactionsListManager() { const query = useQuery({ async queryFn() { const data = await new Promise<{transactions: Array<Transaction>}>(resolve => { resolve({ transactions: [] }) }) return data }, queryKey: ['transactions'] }) // 使用适配函数转换类型 return new DataListManager(adaptToQueryResult(query), "transactions") }
关键说明
- 若业务需处理错误状态,优先选择方法1扩展
QueryResult,能更准确映射所有状态。 - 方法2的适配函数需根据实际业务逻辑处理错误状态的映射,确保转换后类型符合
QueryResult定义。
内容的提问来源于stack exchange,提问作者Pavel Perevezencev
相关产品推荐
相关产品推荐

