T
tRPC

❓-help

How to properly type function arguments for procedures?

Ttwitch154812/17/2023
I'm using tRPC 10 with trpc/react-query I'm trying to understand how to create a function that receives a procedure and it's input as arguments, so that I can then use that procedure reference to call useQuery and getQueryKey within the function:
function useUserSubscription(input: RouterInputs['collection']['user']['list']) {
// these are the only two things that are different between subscriptions
// and I would really like to make this a more abstract function but i have
// NO CLUE how to type `proc` properly so it works with `getQueryKey`
const proc = trpc.collection.user.list
const subProc = trpc.collection.user.subscribe

const queryClient = useQueryClient()
const queryKey = getQueryKey(proc, input, 'query')
const query = proc.useQuery(input)
type Output = (typeof query)['data']

subProc.useSubscription(
{
companyId: '657e3e34e2d4aa86eb145842',
},
{
onData(event) {
// Optimistically update cache
queryClient.setQueryData<Output>(queryKey, (oldData) => {
return handleSubscription(event, oldData) as Output
})
},
}
)

return query
}
function useUserSubscription(input: RouterInputs['collection']['user']['list']) {
// these are the only two things that are different between subscriptions
// and I would really like to make this a more abstract function but i have
// NO CLUE how to type `proc` properly so it works with `getQueryKey`
const proc = trpc.collection.user.list
const subProc = trpc.collection.user.subscribe

const queryClient = useQueryClient()
const queryKey = getQueryKey(proc, input, 'query')
const query = proc.useQuery(input)
type Output = (typeof query)['data']

subProc.useSubscription(
{
companyId: '657e3e34e2d4aa86eb145842',
},
{
onData(event) {
// Optimistically update cache
queryClient.setQueryData<Output>(queryKey, (oldData) => {
return handleSubscription(event, oldData) as Output
})
},
}
)

return query
}
I'm trying to create a generic useSubscription hook. I want the useSubscription function signature to take in the procedure and it's input, but properly typed. I've tried approaches like:
function useSubscription<TProcedure extends AnyQueryProcedure>(procedure: TProcedure, input: RouterInputs[TProcedure]) {
const queryKey = getQueryKey(procedure)
}
function useSubscription<TProcedure extends AnyQueryProcedure>(procedure: TProcedure, input: RouterInputs[TProcedure]) {
const queryKey = getQueryKey(procedure)
}
But this fails for a number of reasons. The RouterInputs lookup fails because it only supports the top-level routes in my router. Can I access a flat tree of types for inputs? getQueryKey also doesn't like taking in TProcedure when its typed as AnyQueryProcedure, the type errors suggest that it wants a decorated version, but I can't figure out how to type it properly. Any help would be greatly appreciated.

Looking for more? Join the community!