Skip to content

queryOptions ​

The queryOptions method allows you to construct type-safe Query Options.

queryOptions can be used together with @tanstack/react-query APIs that take query options, such as useQuery, useQueries, usePrefetchQuery and QueryClient.fetchQuery among many others.

If you would like to use a query API that is not explicitly supported by openapi-typesafe-react-query, this is the way to go.

Examples ​

useQuery example rewritten using queryOptions.

tsx
import { useQuery } from '@tanstack/react-query';
import { $api } from "./api";

export const App = () => {
  const { data, error, isLoading } = useQuery(
    $api.queryOptions("get", "/users/{user_id}", {
      params: {
        path: { user_id: 5 },
      },
    }),
  );

  if (error) return `An error occurred: ${error.message}`;
  if (!data || isLoading) return "Loading...";

  return <div>{data.firstname}</div>;
};
ts
import createFetchClient from "openapi-typesafe-fetch";
import createClient from "openapi-typesafe-react-query";
import type { paths } from "./my-openapi-3-schema"; // generated by openapi-typesafe

const fetchClient = createFetchClient<paths>({
  baseUrl: "https://myapi.dev/v1/",
});
export const $api = createClient(fetchClient);

Good to Know

Both useQuery and useSuspenseQuery use queryOptions under the hood.

Usage with useQueries.

tsx
import { useQueries } from '@tanstack/react-query';
import { $api } from "./api";

export const useUsersById = (userIds: number[]) => (
  useQueries({
    queries: userIds.map((userId) => (
      $api.queryOptions("get", "/users/{user_id}", {
        params: {
          path: { user_id: userId },
        },
      })
    ))
  })
);
ts
import createFetchClient from "openapi-typesafe-fetch";
import createClient from "openapi-typesafe-react-query";
import type { paths } from "./my-openapi-3-schema"; // generated by openapi-typesafe

const fetchClient = createFetchClient<paths>({
  baseUrl: "https://myapi.dev/v1/",
});
export const $api = createClient(fetchClient);

A helper that takes the same arguments ​

Parameters<typeof $api.queryOptions> takes the arguments of any operation, so a helper can pass them on. TypeScript does not relate the method, the path and the init in it: it checks the path against every path, and the init is required when some operation requires one, so pass {} for a path that needs none (useInvalidateQuery("get", "/items", {})).

ts
import { useQueryClient } from "@tanstack/react-query";
import { $api } from "./api";

export function useInvalidateQuery(...args: Parameters<typeof $api.queryOptions>) {
  const queryClient = useQueryClient();
  const { queryKey } = $api.queryOptions(...args);
  return () => queryClient.invalidateQueries({ queryKey });
}

With TypeScript 7 and a schema with hundreds of paths, this Parameters type is over the compiler's limit (TS2859, excessive complexity): it relates every method to every path. List the arguments of the paths the helper takes instead, such as (path: "/users/{user_id}", init: ...).

ReturnType<typeof $api.queryOptions> is still any, as for the hooks: TypeScript does not match these generic signatures against the (...args: any) => infer R pattern of ReturnType, and ReturnType then falls back to any. Take the arguments, as above, or the QueryKey type, instead of the result.

Api ​

tsx
$api.queryOptions(method, path, options, queryOptions);

Arguments

  • method (required)
    • The HTTP method to use for the request.
    • The method is used as key. See Query Keys for more information.
  • path (required)
    • The pathname to use for the request.
    • Must be an available path for the given method in your schema.
    • The pathname is used as key. See Query Keys for more information.
  • options
    • The fetch options to use for the request.
    • Only required if the OpenApi schema requires parameters.
    • The whole options object (params, headers, body and the rest) is part of the key. See Query Keys for more information.
  • queryOptions
    • Additional query options to pass through.

Returns

  • Query Options
    • Fully typed thus data and error will be correctly inferred.
    • queryKey is [method, path, options], or [method, path] without options. options is the whole object passed as init ({ params: { path: { id: 1 } } }), not only its params.
    • queryFn is set to a fetcher function.

Released under the MIT License. Built on openapi-typescript, openapi-fetch and openapi-react-query.