ggascoigne
ggascoigne4w ago

Types question

I'm slowly migrating an old graphql based project over to trpc v11, using @trpc/tanstack-react-query, and rather liking how it all works, but I'm having some difficulties typing some of the code when I try and wrap some of the queries. I have simple code like this:
export const useGetSettingsQuery = () => {
const trpc = useTRPC()
return useQuery(trpc.settings.getSettings.queryOptions())
}
export const useGetSettingsQuery = () => {
const trpc = useTRPC()
return useQuery(trpc.settings.getSettings.queryOptions())
}
And it works great, but since I have a ton of more complicated apis to migrate, where the variables and the query params change somewhat, I'd like to extract the types for the interface of trpc.<endpoint>.queryOptions. I know how to do this using Parameters<> if trpc were global, but it's not in this pattern, and while I can see that the interface is defined as TRPCQueryOptions<TDef extends ResolverDef>, I basically want to know how I get the type for ResolverDef for my specific endpoint.
2 Replies
BeBoRE
BeBoRE4w ago
Inferring Types | tRPC
It is often useful to access the types of your API within your clients. For this purpose, you are able to infer the types contained in your AppRouter.
ggascoigne
ggascoigneOP3w ago
Yes, that might well be what I want. I was assuming that I should just reuse TRPCQueryOptions, but I might just want the input type (for the variables) and then the stock query options type from @tanstack/query. I think I was making it more complicated than it needed and trying to infer them from the resolver (whatever that actually is). Thanks, I'll try it. In case anyone else lands here, this is what I ended out with.
import { UseQueryOptions } from '@tanstack/react-query'
import { TRPCClientErrorLike } from '@trpc/client'
import { TRPCQueryKey } from '@trpc/tanstack-react-query'

export type LookupValuesQueryResult = RouterOutputs['lookups']['getLookupValues']
export type LookupValue = LookupValuesQueryResult[0]

type BaseQueryOptions<T> = UseQueryOptions<any, TRPCClientErrorLike<any>, T, TRPCQueryKey>
export type QueryOptions<T> = Omit<BaseQueryOptions<T>, 'queryKey' | 'queryFn' | 'initialData'>

export const useGetLookupValuesQuery = (realm: string, opts: QueryOptions<Lookup[]>) => {
const trpc = useTRPC()
return useQuery(trpc.lookups.getLookupValues.queryOptions({ realm }, opts))
}
import { UseQueryOptions } from '@tanstack/react-query'
import { TRPCClientErrorLike } from '@trpc/client'
import { TRPCQueryKey } from '@trpc/tanstack-react-query'

export type LookupValuesQueryResult = RouterOutputs['lookups']['getLookupValues']
export type LookupValue = LookupValuesQueryResult[0]

type BaseQueryOptions<T> = UseQueryOptions<any, TRPCClientErrorLike<any>, T, TRPCQueryKey>
export type QueryOptions<T> = Omit<BaseQueryOptions<T>, 'queryKey' | 'queryFn' | 'initialData'>

export const useGetLookupValuesQuery = (realm: string, opts: QueryOptions<Lookup[]>) => {
const trpc = useTRPC()
return useQuery(trpc.lookups.getLookupValues.queryOptions({ realm }, opts))
}
Not a fan of having to use any, but this seems like the simplest solution that I've found so far. I'll admit that this particular example doesn't really justify the hassle of wrapping the raw trpc api, but that's because I picked a non-distracting example. That said, I am beginning to question all of this, and perhaps I'll just stop wrapping the api. I've always wrapped the various react-query apis in the past, in large part to manage query keys, and trpc already does a great job of that gotcha, and what's left just feels like boiler plate in my code.

Did you find this page helpful?