如何用TypeScript satisfies运算符解决React Hook传参类型问题
解决自定义React Hook的TypeScript参数类型不匹配问题
问题根源
你当前的Query类型定义完全不符合需求:
- 用
FeathersQuery & Model时,要求参数必须同时包含Model的所有必填属性(比如_id、name)和FeathersQuery的属性,这显然和你“条件传入任意属性”的目标矛盾; - 用
FeathersQuery | Model时,TypeScript会要求传入的对象必须完全匹配其中某一个类型的完整结构,而你只传了makeId,既不是完整的FeathersQuery也不是完整的Model,因此触发类型错误。
你的核心需求是:参数可以自由传入FeathersQuery的任意属性,或者Model的任意属性(作为筛选条件),所有属性均为可选。
解决方案
1. 修正Query类型定义
将Query改为FeathersQuery & Partial<Model>,Partial<Model>会把Model的所有属性转为可选,完美支持任意组合的筛选条件和Feathers查询参数:
// 替换原有Query类型 type Query = FeathersQuery & Partial<Model>;
2. (可选)用satisfies做实时类型校验
如果你想在编写代码时就校验传入的参数是否符合合法结构,但又不想让TypeScript过度限制参数的字面量类型,可以使用satisfies运算符:
const { data: models } = useFetchModels({ makeId: selectedMakeId, $sort: { name: 1 } // 同时传入Feathers排序参数 } satisfies Query);
完整修正后的Hook代码
import { useQuery } from 'react-query'; import { axiosClient } from '@src/features/@Api'; import type { FeathersFind, FeathersQuery, } from '@features/@Api/@types/feathers'; import type { Model } from '@features/@Api/@types/models'; type Result = FeathersFind & { data: Model[]; }; // 修正后的Query类型,支持任意可选属性组合 type Query = FeathersQuery & Partial<Model>; export const useFetchModels = (query?: Query) => { const defaultQuery = { $limit: 1000, $sort: { createdAt: -1, }, ...(query || {}), }; const { isFetching, isLoading, refetch, data, ...rest } = useQuery( ['query-models', query], // 把query加入查询键,参数变化时自动重新查询 async () => { const { data }: { data: Result } = await axiosClient.get('/models', { params: defaultQuery, }); return data; }, { cacheTime: 1000 * 60 * 60, } ); return { isFetching, isLoading, refetch, data, ...rest }; };
额外说明
Partial<Model>是解决问题的核心,它让Model的所有属性从必填转为可选,允许你只传makeId这类单个筛选条件;- 结合
FeathersQuery后,还能同时传入$limit、$sort等Feathers专属查询参数; - 优化点:将
query加入React Query的查询键数组,确保不同参数触发重新查询,避免缓存数据不一致。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

