thomasplayschess
thomasplayschess13mo ago

Wrapping useQuery into a custom hook

I'm trying to wrap useQuery into a custom hook (as I have some legacy code that I need to run before). Example:
trpc.myendpoint.useQuery({ foo: 'bar' });
// instead of the code above, I want to write this:
useCustomHook(trpc.myendpoint, { foo: 'bar' })
trpc.myendpoint.useQuery({ foo: 'bar' });
// instead of the code above, I want to write this:
useCustomHook(trpc.myendpoint, { foo: 'bar' })
I'm able to write the JavaScript code, but I have trouble getting the TypeScript types right. I have more information in the Stackoverflow question here: https://stackoverflow.com/q/77096846 Thanks for any help ❤️
35 Replies
funki
funki13mo ago
@thomasplayschess TrpcProcedure is definitely not right because it could be a query or a mutation or an observable/subscription. if you wanna "hard-code" useQuery into your function without testing for the other possible types, use a narrower type instead. idk which type that would be but probably something like TrpcQueryProcedure. (might be named differently, just guessing). you'll find the right one for sure.
thomasplayschess
thomasplayschess13mo ago
I found DecorateProcedure which works like this: DecorateProcedure<AppRouter['_def']['record']['PROCNAME'], any, 'PROCNAME'> but was not able to make this work for all procedures. Using a narrower type works, but I want this to be generic. I get it to work for a single procedure, but I thought there must be a type that makes this work across all procedures.
funki
funki13mo ago
well first of all you don't want to make it work for all procedures obviously, only for the query procedures. otherwise you wouldn't ask for useQuery specifically. right?
thomasplayschess
thomasplayschess13mo ago
Oh, okay. My bad. You are right. Yes, sorry, wasn't sure on the wording.
funki
funki13mo ago
that type doesn't sound like what you're looking for. can you send the type definition of TrpcProcedure? it might be a union of the stuff you need.
thomasplayschess
thomasplayschess13mo ago
TrpcProcedure is the one that I made up in the stackoverflow question.
funki
funki13mo ago
oh
thomasplayschess
thomasplayschess13mo ago
For example this one: type TrpcProcedure = (typeof trpc)[keyof AppRouter['_def']['procedures']]; (which doesn't work)
funki
funki13mo ago
you wanna dive into tRPC's types. ctrl-click an existing, working useQuery it might be scary tho
thomasplayschess
thomasplayschess13mo ago
That's what I did to get to DecorateProcedure<AppRouter... but these types are really like A extends B extends C extends D | E extends F Seems it would take me days to get into it tbh 🙈
funki
funki13mo ago
i don't think you need to derive the generic type from your own router. it's possible to write a function like what you want that should work with any router.
thomasplayschess
thomasplayschess13mo ago
As you said, it's super scary...
funki
funki13mo ago
have you tried AnyQueryProcedure? i just looked around the tRPC docs and searched for "types" and eventually came across that.
thomasplayschess
thomasplayschess13mo ago
I think I used this somewhere. But honestly I think I've used up to 10 different interfaces up to now. Problem is that many are also generic and look just like the DecorateProcedure above (with 3 generics).
funki
funki13mo ago
you'll certainly need another type that the queryprocedure type takes as an argument in order to contract the params to it. i'm looking for a tRPC react playground right now