---
url: >-
  https://openapi-typesafe.github.io/openapi-typesafe/react-query/query-options.md
description: >-
  Build type-safe TanStack Query options for useQueries, prefetching and
  fetchQuery
---

# {{ $frontmatter.title }}

The `queryOptions` method allows you to construct type-safe [Query Options](https://tanstack.com/query/latest/docs/framework/react/guides/query-options).

`queryOptions` can be used together with `@tanstack/react-query` APIs that take query options, such as
[useQuery](https://tanstack.com/query/latest/docs/framework/react/reference/useQuery),
[useQueries](https://tanstack.com/query/latest/docs/framework/react/reference/useQueries),
[usePrefetchQuery](https://tanstack.com/query/latest/docs/framework/react/reference/usePrefetchQuery) and
[QueryClient.fetchQuery](https://tanstack.com/query/latest/docs/reference/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](use-query#example) rewritten using `queryOptions`.

::: code-group

```tsx [src/app.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 [src/api.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);
```

:::

::: info Good to Know

Both [useQuery](use-query) and [useSuspenseQuery](use-suspense-query) use `queryOptions` under the hood.

:::

Usage with [useQueries](https://tanstack.com/query/latest/docs/framework/react/reference/useQueries).

::: code-group

```tsx [src/use-users-by-id.ts]
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 [src/api.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 [src/use-invalidate-query.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](https://tanstack.com/query/latest/docs/framework/react/guides/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](https://tanstack.com/query/latest/docs/framework/react/guides/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](https://tanstack.com/query/latest/docs/framework/react/guides/query-keys) for more information.
* `queryOptions`
  * Additional query options to pass through.

**Returns**

* [Query Options](https://tanstack.com/query/latest/docs/framework/react/guides/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.
