From c2562a40e9a0f60a779aa93c0671f39e6e76e36e Mon Sep 17 00:00:00 2001 From: Gianmarco Rengucci Date: Mon, 9 Feb 2026 16:17:45 +0100 Subject: [PATCH] feat(openapi-react-query): use DataTag for queryKey in queryOptions --- packages/openapi-react-query/src/index.ts | 12 +++--- .../openapi-react-query/test/index.test.tsx | 43 +++++++++++++++++++ 2 files changed, 50 insertions(+), 5 deletions(-) diff --git a/packages/openapi-react-query/src/index.ts b/packages/openapi-react-query/src/index.ts index e3c67419f..fb9683164 100644 --- a/packages/openapi-react-query/src/index.ts +++ b/packages/openapi-react-query/src/index.ts @@ -1,4 +1,5 @@ import { + type DataTag, type InfiniteData, type QueryClient, type QueryFunctionContext, @@ -65,8 +66,9 @@ export type QueryOptionsFunction, QueryKey >, - "queryFn" + "queryFn" | "queryKey" > & { + queryKey: DataTag, Response["data"], Response["error"]>; queryFn: Exclude< UseQueryOptions< Response["data"], @@ -209,10 +211,10 @@ export default function createClient = (method, path, ...[init, options]) => ({ - queryKey: (init === undefined ? ([method, path] as const) : ([method, path, init] as const)) as QueryKey< - Paths, - typeof method, - typeof path + queryKey: (init === undefined ? ([method, path] as const) : ([method, path, init] as const)) as DataTag< + QueryKey, + any, + any >, queryFn, ...options, diff --git a/packages/openapi-react-query/test/index.test.tsx b/packages/openapi-react-query/test/index.test.tsx index b9978935c..78715e643 100644 --- a/packages/openapi-react-query/test/index.test.tsx +++ b/packages/openapi-react-query/test/index.test.tsx @@ -91,6 +91,49 @@ describe("client", () => { client.queryOptions("get", "/blogposts/{post_id}", {}); }); + it("correctly infers return type from query key", async () => { + const fetchClient = createFetchClient({ baseUrl }); + const client = createClient(fetchClient); + + const initialData = { title: "Initial data", body: "Initial data" }; + + const options = client.queryOptions( + "get", + "/blogposts/{post_id}", + { + params: { + path: { + post_id: "1", + }, + }, + }, + { + initialData: () => initialData, + }, + ); + + const data = queryClient.getQueryData(options.queryKey); + + expectTypeOf(data).toEqualTypeOf< + | { + title: string; + body: string; + publish_date?: number; + } + | undefined + >(); + expect(data).toEqual(undefined); + + const { result } = renderHook(() => useQuery({ ...options, enabled: false, select: (data) => data }), { + wrapper, + }); + + await waitFor(() => expect(result.current.isFetching).toBe(false)); + + expect(result.current.data).toEqual(initialData); + expect(result.current.error).toBeNull(); + }); + it("returns query options that can resolve data correctly with fetchQuery", async () => { const response = { title: "title", body: "body" }; const fetchClient = createFetchClient({ baseUrl });