Firestore分页添加文档至数组时TypeScript类型报错问题
我使用Firebase从Firestore读取数据,借助其分页功能尝试将新获取的值添加到现有数组中,但调用setState钩子时TypeScript抛出了类型不匹配的错误。
代码示例
interface DOCUMENT { docId: string; title: string; coverImage: string; width: number; height: number; likesId: string[]; follower: string[]; hasChecked: boolean; } export default function Home() { const [results, setResults] = useState<DOCUMENT[]>([]); useEffect(() => { const nextOnes = async () => { const documents: DOCUMENT[] = []; const next = query( collection(db, "documents"), orderBy("createdAt", "asc"), startAfter(lastVisible), limit(3) ); const documentSnapshots = await getDocs(next); documentSnapshots.forEach((doc) => { documents.push(doc.data() as DOCUMENT); }); // 错误发生在这里 setResults((prev) => [...prev, documents]); }; inView && nextOnes(); }, [inView, lastVisible]); ... }
错误提示
Argument of type '(prev: DOCUMENT[]) => (DOCUMENT | DOCUMENT[])[]' is not assignable to parameter of type 'SetStateAction<DOCUMENT[]>'.
Type '(prev: DOCUMENT[]) => (DOCUMENT | DOCUMENT[])[]' is not assignable to type '(prevState: DOCUMENT[]) => DOCUMENT[]'.
Type '(DOCUMENT | DOCUMENT[])[]' is not assignable to type 'DOCUMENT[]'.
Type 'DOCUMENT | DOCUMENT[]' is not assignable to type 'DOCUMENT'.
Type 'DOCUMENT[]' is missing the following properties from type 'DOCUMENT': docId, title, coverImage, width, and 4 more.
问题根源是setResults的更新逻辑错误:你将整个documents数组作为单个元素插入到了原数组prev中,导致最终数组的元素类型变成了DOCUMENT | DOCUMENT[],与results定义的DOCUMENT[]类型不兼容。
只需修改更新逻辑,用扩展运算符将documents的所有元素展开后合并到原数组:
// 修正后的代码 setResults((prev) => [...prev, ...documents]);
这样合并后的数组仍然是纯DOCUMENT[]类型,完全符合TypeScript的类型要求,错误会直接消失。
你也可以使用数组的concat方法实现相同效果,写法更简洁:
setResults((prev) => prev.concat(documents));
两种方式都能解决类型不匹配问题,根据个人习惯选择即可。
内容的提问来源于stack exchange,提问作者Captai-N

