Firestore查询React Hook调用query方法抛出重载不匹配错误
错误原因
两个报错本质是同一个根因引发的连锁反应,核心问题只有一个:
query()函数的约束参数是剩余参数设计,类型签名为query(queryRef: Query, ...queryConstraints: QueryConstraint[]),也就是说从第二个参数开始,你需要逐个传入QueryConstraint对象,不能直接把一整个QueryConstraint数组作为第二个参数传入。- 你直接传入数组后,TS会认为你给第二个参数传了一个数组类型的值,不符合单个
QueryConstraint的类型要求,匹配重载失败。此时TS会依次尝试所有重载签名给出错误提示,才会顺带抛出「CollectionReference不匹配Query」的误导性报错——实际上 CollectionReference本身就是Query的子类,正常传参时完全兼容第一个参数的类型要求,这个报错是参数传递错误引发的连带假报错。
另外你的转换函数里参数名有拼写错误:queryConstaints 正确拼写应为 queryConstraints(少了字母r),虽然不直接引发当前类型错误,但容易埋下后续维护的隐患。
修复方案
核心修改只有一处:调用query()时,用展开运算符...把转换得到的约束数组拆成逐个参数传入即可。
修改后的getRefQuery代码如下:
const getRefQuery = ({ path, queryConstraints }: GetRefQueryParams) => { // 展开数组,适配query的剩余参数类型要求 return query(getPathRef(path), ...convertArrayQueryClauses(queryConstraints)) };
修改后TS就能正确匹配重载签名,两个报错都会消失。
可选类型优化
建议去掉转换函数里的any类型,补充明确的入参类型定义,从源头避免传参错误:
// 先定义自定义查询子句的类型 import type { WhereFilterOp, OrderByDirection, QueryConstraint } from "firebase/firestore"; type CustomQueryClause = { where?: string; operator?: WhereFilterOp; value?: unknown; orderBy?: string; direction?: OrderByDirection; limit?: number; } function convertArrayQueryClauses(queryConstraints: CustomQueryClause[]) { const newQueryConstraints: QueryConstraint[] = [] for(const item of queryConstraints) { // 补充必要的属性判断,避免传参缺失导致运行时报错 if(item.where && item.operator) { newQueryConstraints.push(where(item.where, item.operator, item.value)) } if(item.orderBy) { newQueryConstraints.push(orderBy(item.orderBy, item.direction)) } if(typeof item.limit === 'number') { newQueryConstraints.push(limit(item.limit)) } } return newQueryConstraints }
内容的提问来源于stack exchange,提问作者Saul Anstey
相关产品推荐
相关产品推荐

