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

React Query+TS扩展useQuery强制queryKey为至少2项数组的方法

扩展useQuery实现queryKey强制校验方案

1. 扩展原生useQuery的实现方式

不需要重写react-query的核心逻辑,只需要写一层薄包装函数:

  • 内部直接透传所有参数给原生useQuery,完全复用原有所有功能(缓存、状态管理、配置项等都不受影响)
  • 可选在开发环境增加运行时校验,避免TS被any等类型绕过的非法传参
  • 保留原生useQuery的全部泛型推导能力,不会丢失data、error等字段的类型提示

2. TypeScript类型规则定义

核心是用TS可变元组类型约束queryKey必须为至少包含2个元素的数组,基础类型定义为:

// 约束目标:最少2个元素的数组
type ValidQueryKey = [unknown, unknown, ...unknown[]];

这个类型会自动过滤两种非法传参:

  • 非数组类型(比如单独传字符串作为queryKey)
  • 数组长度小于2的情况

完整实现代码

// 导入原生useQuery,注意v4+版本包名为@tanstack/react-query,v3及更早为react-query
import { useQuery as baseUseQuery } from '@tanstack/react-query';
import type { UseQueryOptions, UseQueryResult } from '@tanstack/react-query';

// 定义合法queryKey类型:长度至少为2的数组
type ValidQueryKey = [unknown, unknown, ...unknown[]];

// 重载1:支持(queryKey, options)传参格式
export function useQuery<
  TQueryFnData = unknown,
  TError = unknown,
  TData = TQueryFnData,
  TQueryKey extends ValidQueryKey = ValidQueryKey
>(
  queryKey: TQueryKey,
  options?: Omit<UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>, 'queryKey'>
): UseQueryResult<TData, TError>;

// 重载2:支持(queryKey, queryFn, options)传参格式
export function useQuery<
  TQueryFnData = unknown,
  TError = unknown,
  TData = TQueryFnData,
  TQueryKey extends ValidQueryKey = ValidQueryKey
>(
  queryKey: TQueryKey,
  queryFn: UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>['queryFn'],
  options?: Omit<UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>, 'queryKey' | 'queryFn'>
): UseQueryResult<TData, TError>;

// 实现层
export function useQuery(
  queryKey: ValidQueryKey,
  arg2?: any,
  arg3?: any
) {
  // 开发环境运行时校验,不需要可直接删除
  if (process.env.NODE_ENV !== 'production') {
    if (!Array.isArray(queryKey)) {
      throw new Error('queryKey必须是数组类型');
    }
    if (queryKey.length < 2) {
      throw new Error('queryKey数组至少需要包含2个元素');
    }
  }

  // 透传参数给原生useQuery
  return baseUseQuery(queryKey, arg2, arg3);
}

校验效果验证

对应给出的用例:

const { data } = useQuery<Data, Error>(["module_1", "fetchA"], fetchFn); // ✅ 校验通过
const { data } = useQuery<Data, Error>("module_1", fetchFn); // ❌ TS报错:类型string不符合ValidQueryKey约束
const { data } = useQuery<Data, Error>(["module_1"], fetchFn); // ❌ TS报错:元组长度为1,不足2位

注意:该实现依赖TS 4.0及以上版本支持的可变元组特性,目前绝大多数前端项目的TS版本都满足该要求。

内容的提问来源于stack exchange,提问作者Zuy BK

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 02:57:20