From fc4e1d15bfb7ac7ff6490d867f34bed3c4defd3f Mon Sep 17 00:00:00 2001
From: Adam Michel <adam@amichel.me>
Date: Mon, 24 Feb 2025 15:00:12 -0800
Subject: [PATCH 1/5] Infer select return from useInfiniteQuery

---
 packages/openapi-react-query/src/index.ts | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/packages/openapi-react-query/src/index.ts b/packages/openapi-react-query/src/index.ts
index 855b249c9..88a1753f9 100644
--- a/packages/openapi-react-query/src/index.ts
+++ b/packages/openapi-react-query/src/index.ts
@@ -110,7 +110,7 @@ export type UseInfiniteQueryMethod<Paths extends Record<string, Record<HttpMetho
     UseInfiniteQueryOptions<
       Response["data"],
       Response["error"],
-      InfiniteData<Response["data"]>,
+      InferSelectReturnType<InfiniteData<Response["data"]>, Options["select"]>,
       Response["data"],
       QueryKey<Paths, Method, Path>,
       unknown
@@ -125,7 +125,7 @@ export type UseInfiniteQueryMethod<Paths extends Record<string, Record<HttpMetho
   init: InitWithUnknowns<Init>,
   options: Options,
   queryClient?: QueryClient,
-) => UseInfiniteQueryResult<InfiniteData<Response["data"]>, Response["error"]>;
+) => UseInfiniteQueryResult<InferSelectReturnType<InfiniteData<Response["data"]>, Options["select"]>, Response["error"]>;
 
 export type UseSuspenseQueryMethod<Paths extends Record<string, Record<HttpMethod, {}>>, Media extends MediaType> = <
   Method extends HttpMethod,

From d7853fa275a72056a60cb8c50475129ef1cf7410 Mon Sep 17 00:00:00 2001
From: Adam Michel <adam@amichel.me>
Date: Mon, 24 Feb 2025 15:08:07 -0800
Subject: [PATCH 2/5] Include useInfiniteQuery in docs and update

---
 docs/.vitepress/en.ts                          | 4 ++++
 docs/openapi-react-query/use-infinite-query.md | 1 +
 2 files changed, 5 insertions(+)

diff --git a/docs/.vitepress/en.ts b/docs/.vitepress/en.ts
index a15fe27cb..4fa344bdd 100644
--- a/docs/.vitepress/en.ts
+++ b/docs/.vitepress/en.ts
@@ -80,6 +80,10 @@ export default defineConfig({
               text: "useSuspenseQuery",
               link: "/use-suspense-query",
             },
+            {
+              text: "useInfiniteQuery",
+              link: "/use-infinite-query",
+            },
             {
               text: "queryOptions",
               link: "/query-options",
diff --git a/docs/openapi-react-query/use-infinite-query.md b/docs/openapi-react-query/use-infinite-query.md
index 86bcbad1e..7824baa1a 100644
--- a/docs/openapi-react-query/use-infinite-query.md
+++ b/docs/openapi-react-query/use-infinite-query.md
@@ -105,6 +105,7 @@ const query = $api.useInfiniteQuery(
   - Only required if the OpenApi schema requires parameters.
   - The options `params` are used as key. See [Query Keys](https://tanstack.com/query/latest/docs/framework/react/guides/query-keys) for more information.
 - `infiniteQueryOptions`
+  - `pageParamName` The query param name used for pagination, `"cursor"` by default.
   - The original `useInfiniteQuery` options.
   - [See more information](https://tanstack.com/query/latest/docs/framework/react/reference/useInfiniteQuery)
 - `queryClient`

From c457082aef0600db50f875f1c959415a52a48436 Mon Sep 17 00:00:00 2001
From: Adam Michel <adam@amichel.me>
Date: Mon, 24 Feb 2025 15:21:25 -0800
Subject: [PATCH 3/5] Add type test for selects on useInfiniteQuery

---
 .../openapi-react-query/test/index.test.tsx   | 64 +++++++++++++++++++
 1 file changed, 64 insertions(+)

diff --git a/packages/openapi-react-query/test/index.test.tsx b/packages/openapi-react-query/test/index.test.tsx
index 5ccda7a42..3dd84f87a 100644
--- a/packages/openapi-react-query/test/index.test.tsx
+++ b/packages/openapi-react-query/test/index.test.tsx
@@ -1087,5 +1087,69 @@ describe("client", () => {
       const allItems = result.current.data?.pages.flatMap((page) => page.items);
       expect(allItems).toEqual([1, 2, 3, 4, 5, 6]);
     });
+    it('should use return type from select option', async () => {
+      const fetchClient = createFetchClient<paths>({ baseUrl });
+      const client = createClient(fetchClient);
+
+      // First page request handler
+      const firstRequestHandler = useMockRequestHandler({
+        baseUrl,
+        method: "get",
+        path: "/paginated-data",
+        status: 200,
+        body: { items: [1, 2, 3], nextPage: 1 },
+      });
+
+      const { result, rerender } = renderHook(
+        () =>
+          client.useInfiniteQuery(
+            "get",
+            "/paginated-data",
+            {
+              params: {
+                query: {
+                  limit: 3,
+                },
+              },
+            },
+            {
+              getNextPageParam: (lastPage) => lastPage.nextPage,
+              initialPageParam: 0,
+              select: (data) => data.pages.flatMap((page) => page.items).filter((item) => item !== undefined),
+            },
+          ),
+        { wrapper },
+      );
+
+      // Wait for initial query to complete
+      await waitFor(() => expect(result.current.isSuccess).toBe(true));
+
+      expectTypeOf(result.current.data).toEqualTypeOf<number[] | undefined>();
+      expect(result.current.data).toEqual([1, 2, 3]);
+
+      // Set up mock for second page before triggering next page fetch
+      const secondRequestHandler = useMockRequestHandler({
+        baseUrl,
+        method: "get",
+        path: "/paginated-data",
+        status: 200,
+        body: { items: [4, 5, 6], nextPage: 2 },
+      });
+
+      // Fetch next page
+      await act(async () => {
+        await result.current.fetchNextPage();
+        // Force a rerender to ensure state is updated
+        rerender();
+      });
+
+      // Wait for second page to be fetched and verify loading states
+      await waitFor(() => {
+        expect(result.current.isFetching).toBe(false);
+        expect(result.current.hasNextPage).toBe(true);
+      });
+
+      expect(result.current.data).toEqual([1, 2, 3, 4, 5, 6]);
+    });
   });
 });

From 16ba2147446c81ece56467f7a7563c757faa2515 Mon Sep 17 00:00:00 2001
From: Adam Michel <adam@amichel.me>
Date: Mon, 24 Feb 2025 15:30:05 -0800
Subject: [PATCH 4/5] Add changeset

---
 .changeset/seven-monkeys-fetch.md | 5 +++++
 1 file changed, 5 insertions(+)
 create mode 100644 .changeset/seven-monkeys-fetch.md

diff --git a/.changeset/seven-monkeys-fetch.md b/.changeset/seven-monkeys-fetch.md
new file mode 100644
index 000000000..10e4e6e32
--- /dev/null
+++ b/.changeset/seven-monkeys-fetch.md
@@ -0,0 +1,5 @@
+---
+"openapi-react-query": minor
+---
+
+[#2169](https://github.com/openapi-ts/openapi-typescript/pull/2169): Infer returned `data` type from `select` option when used with the `useInfiniteQuery` method.

From 78225d21435cf44e8f80532c45eb30163dd464c8 Mon Sep 17 00:00:00 2001
From: Adam Michel <adam@amichel.me>
Date: Mon, 24 Feb 2025 15:34:21 -0800
Subject: [PATCH 5/5] Fix linter errors

---
 packages/openapi-react-query/src/index.ts        | 5 ++++-
 packages/openapi-react-query/test/index.test.tsx | 2 +-
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/packages/openapi-react-query/src/index.ts b/packages/openapi-react-query/src/index.ts
index 88a1753f9..97fd9ce1e 100644
--- a/packages/openapi-react-query/src/index.ts
+++ b/packages/openapi-react-query/src/index.ts
@@ -125,7 +125,10 @@ export type UseInfiniteQueryMethod<Paths extends Record<string, Record<HttpMetho
   init: InitWithUnknowns<Init>,
   options: Options,
   queryClient?: QueryClient,
-) => UseInfiniteQueryResult<InferSelectReturnType<InfiniteData<Response["data"]>, Options["select"]>, Response["error"]>;
+) => UseInfiniteQueryResult<
+  InferSelectReturnType<InfiniteData<Response["data"]>, Options["select"]>,
+  Response["error"]
+>;
 
 export type UseSuspenseQueryMethod<Paths extends Record<string, Record<HttpMethod, {}>>, Media extends MediaType> = <
   Method extends HttpMethod,
diff --git a/packages/openapi-react-query/test/index.test.tsx b/packages/openapi-react-query/test/index.test.tsx
index 3dd84f87a..1062bafd7 100644
--- a/packages/openapi-react-query/test/index.test.tsx
+++ b/packages/openapi-react-query/test/index.test.tsx
@@ -1087,7 +1087,7 @@ describe("client", () => {
       const allItems = result.current.data?.pages.flatMap((page) => page.items);
       expect(allItems).toEqual([1, 2, 3, 4, 5, 6]);
     });
-    it('should use return type from select option', async () => {
+    it("should use return type from select option", async () => {
       const fetchClient = createFetchClient<paths>({ baseUrl });
       const client = createClient(fetchClient);