如何移除React Query InfiniteQuery中pageParam的额外类型检查
移除TanStack React Query InfiniteQuery中的pageParam类型检查方案
我在用TanStack React Query实现InfiniteQuery时,必须额外检查pageParam的number类型才能正常运行,现在希望在不改变现有文件结构的前提下简化代码,移除以下类型检查逻辑,求可行的重构方案:
queryFn: ({pageParam}) => { if (typeof pageParam === 'number') return UseTodoService.getAll(pageParam); else throw new Error("pageParam must be a number."); },
现有代码文件如下:
ApiClient.ts
import axios from "axios"; const apiClient = axios.create({ baseURL: 'https://jsonplaceholder.typicode.com/' }) class API<T> { constructor(public endpoint: string) { } getAll = (pageParam: number) => { return apiClient.get<T[]>(this.endpoint, { params: { _page: pageParam } }).then(res => res.data) .catch(err => err) } } export default API
todo-service.ts
import API from "../api-service/api-client.ts"; export interface Todo { userId: number; id: number; title: string; completed: boolean; } const UseTodoService = new API<Todo>('todos') export default UseTodoService;
useTodo hook
import {useInfiniteQuery} from "@tanstack/react-query"; import {CACHE_KEY_TODO} from "../constants.ts"; import UseTodoService, {Todo} from "../http-service/todo-service.ts"; const UseTodo = () => { return useInfiniteQuery<Todo[], Error>({ queryKey: CACHE_KEY_TODO, queryFn: ({pageParam}) => { if (typeof pageParam === 'number') return UseTodoService.getAll(pageParam); else throw new Error("pageParam must be a number."); }, getNextPageParam: (lastPage, allPages) => lastPage.length > 0 ? allPages.length + 1 : undefined, initialPageParam: 1 }) } export default UseTodo;
Todo component
import useTodo from "../hooks/useTodo.ts"; function TodoList() { const {data, fetchNextPage } = useTodo() return <> <h1>TodoList</h1> <ul className="list-group"> {data?.pages.map(todos => todos.map((todo, index) => <li className="list-group-item" key={index}>{todo.title}</li>))} </ul> <button onClick={() => fetchNextPage()} className="btn btn-primary mt-2">Fetch More</button> </> } export default TodoList;
重构方案:利用TypeScript泛型强化类型约束
核心思路是通过TypeScript的泛型明确useInfiniteQuery中pageParam的类型,让编译期完成类型校验,彻底消除运行时的类型检查逻辑。
修改useTodo hook的代码,补充useInfiniteQuery的完整泛型参数,指定pageParam为number类型:
import {useInfiniteQuery} from "@tanstack/react-query"; import {CACHE_KEY_TODO} from "../constants.ts"; import UseTodoService, {Todo} from "../http-service/todo-service.ts"; const UseTodo = () => { return useInfiniteQuery<Todo[], Error, Todo[], number>({ queryKey: CACHE_KEY_TODO, queryFn: ({pageParam}) => UseTodoService.getAll(pageParam), getNextPageParam: (lastPage, allPages) => lastPage.length > 0 ? allPages.length + 1 : undefined, initialPageParam: 1 }) } export default UseTodo;
方案说明:
useInfiniteQuery的泛型参数顺序为:QueryData, Error, PageData, PageParam,显式指定PageParam为number后,TypeScript会自动约束pageParam的类型。- 你的
initialPageParam是1(number类型),getNextPageParam返回值要么是allPages.length + 1(number)要么是undefined,完全符合类型约束,编译期就能确保pageParam不会出现非number值。 - 移除运行时类型检查后,代码更简洁,同时类型安全由TypeScript编译期保障,不会丢失原有校验能力。
内容的提问来源于stack exchange,提问作者Oleksandr Stoliarchuk
相关产品推荐
相关产品推荐

