new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

TanStack Query · React · all subjects

typescript

23 notes, read out of this brain and free to use. Each one was extracted from a source and is re-checked against its exam.

TypeScript version support requirement

TanStack Query follows DefinitelyTyped's support window and supports TypeScript versions released within the last 2 years. At the moment, that means TypeScript 5.4 and newer.

Type changes are non-breaking patch releases

Changes to types in the TanStack Query repository are considered non-breaking and are usually released as patch semver changes, because otherwise every type enhancement would be a major version.

Lock react-query package to specific patch release

It is highly recommended that you lock your react-query package version to a specific patch release and upgrade with the expectation that types may be fixed or upgraded between any release.

Type inference from queryFn return type

Types in TanStack Query generally flow through very well so that you don't have to provide type annotations yourself. The data type is inferred from the queryFn's return type. For example, if queryFn returns Promise.resolve(5), the data type is number | undefined.

Type inference with select option

When using the select option in useQuery, the data type is inferred from the select function's return type. For example, if select transforms data to data.toString(), the data type becomes string | undefined.

Ensure queryFn has well-defined return type

Type inference works best if your queryFn has a well-defined returned type. Most data fetching libraries return any by default, so extract the fetching logic to a properly typed function to get proper type inference.

Type narrowing with status field and boolean flags

TanStack Query uses a discriminated union type for the query result, discriminated by the status field and derived status boolean flags. You can check for success status to narrow the data type from undefined to the actual type.

Error field default type is Error

The type for the error field defaults to Error, because that is what most users expect.

Specify custom error type with generic

You can specify the type of the error field using a generic argument to useQuery, for example useQuery<Group[], string>(['groups'], fetchGroups) makes error type string | null. However, this has the drawback that type inference for all other generics of useQuery will not work anymore.

Type narrow error field with axios.isAxiosError

Instead of specifying a custom error type via generics, you can use type narrowing with functions like axios.isAxiosError(error) to make the error field more specific without losing type inference on other generics.

Register global Error type with Register interface

TanStack Query v5 allows setting a global Error type for everything by amending the Register interface without specifying generics on call-sides. This maintains inference while making the error field have the specified type. Set defaultError to unknown to enforce that call sites must do explicit type-narrowing.

Global Error type registration example

To register a global Error type in TypeScript: import '@tanstack/react-query' declare module '@tanstack/react-query' { interface Register { // Use unknown so call sites must narrow explicitly. defaultError: unknown } } After this, error on useQuery will be typed as unknown | null.

Register global Meta type

Similarly to registering a global error type, you can register a global Meta type to ensure the optional meta field on queries and mutations stays consistent and is type-safe. The registered type must extend Record<string, unknown> so that meta remains an object.

Global Meta type registration example

To register a global Meta type in TypeScript: import '@tanstack/react-query' interface MyMeta extends Record<string, unknown> { // Your meta type definition. } declare module '@tanstack/react-query' { interface Register { queryMeta: MyMeta mutationMeta: MyMeta } }

Register global QueryKey and MutationKey types

Similarly to registering a global error type, you can register global QueryKey and MutationKey types. This allows you to provide more structure to your keys that matches your application's hierarchy and have them be typed across all of the library's surface area. The registered type must extend the Array type so that your keys remain an array.

Global QueryKey type registration example

To register a global QueryKey type in TypeScript: import '@tanstack/react-query' type QueryKey = ['dashboard' | 'marketing', ...ReadonlyArray<unknown>] declare module '@tanstack/react-query' { interface Register { queryKey: QueryKey mutationKey: QueryKey } }

Use queryOptions helper to maintain type inference

When extracting query options into a separate function to share them between useQuery and prefetchQuery, use the queryOptions helper to maintain type inference. This helper preserves the relationship between queryKey and queryFn.

queryOptions helper example

To extract query options with type inference: import { queryOptions } from '@tanstack/react-query' function groupOptions() { return queryOptions({ queryKey: ['groups'], queryFn: fetchGroups, staleTime: 5 * 1000, }) } useQuery(groupOptions()) queryClient.prefetchQuery(groupOptions())

queryOptions enables type inference for getQueryData

The queryKey returned from queryOptions knows about the queryFn associated with it. This type information makes functions like queryClient.getQueryData aware of those types, so queryClient.getQueryData(groupOptions().queryKey) will be typed as Group[] | undefined instead of unknown.

getQueriesData requires explicit type specification

Type inference via queryOptions does not work for queryClient.getQueriesData because it returns an array of tuples with heterogeneous, unknown data. If you are sure of the type of data that your query will return, specify it explicitly: queryClient.getQueriesData<Group[]>(groupOptions().queryKey)

Use mutationOptions helper for mutation type inference

Similarly to queryOptions, you can use mutationOptions to extract mutation options into a separate function while maintaining type inference.

mutationOptions helper example

To extract mutation options with type inference: function groupMutationOptions() { return mutationOptions({ mutationKey: ['addGroup'], mutationFn: addGroup, }) } useMutation({ ...groupMutationOptions(), onSuccess: () => queryClient.invalidateQueries({ queryKey: ['groups'] }), }) useIsMutating(groupMutationOptions()) queryClient.isMutating(groupMutationOptions())

Use skipToken to typesafely disable queries

In TypeScript, you can use skipToken to disable a query based on a condition while keeping the query type-safe. See the Disabling Queries guide for more details.

Give your agent this brain