-
-
Notifications
You must be signed in to change notification settings - Fork 27
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Is there way to create wrapper function for route handler inferring schema type? #97
Comments
@sinclairzx81 Hi, I'm wondering if you can take a look if that's possible with typescript? Thanks. |
@benevbright Hi! I had a quick look. Unfortunately, I don't think this pattern will be possible with Type Providers as the request context (for request and response types) don't have any way to propagate into the wrapper when assigning functions that way. The following are 3 implementations of this pattern, ranging from explicit function calls to closure assignment (as per your example). This just to show where things go wrong. Wrapper FunctionHere's the wrapper function used on all 3 examples. type Callback<Request, Response> = (request: Request, response: Response) => any
function wrapper<
Request = unknown,
Response = unknown
>(callback: Callback<Request, Response>): Callback<Request, Response> {
// todo: implement wrapper stuff here ...
return (request, response) => callback(request, response)
} Form 1Explicit unwrap calls in the handler, specify req/res types via generics. The following works fine (albeit verbose) fastify.post('/', {
schema: {
body: Type.Number(),
response: { 200: Type.Number() } }
}, (req, res) => {
const closure = wrapper<typeof req, typeof res>((req, res) => {
// handle request
})
closure(req, res) // important! For this call to be type safe, you need
// the signature derived via generics (see typeof)
}) Form 2Reduce call to inline closure, retain generics, return fastify.post('/', {
schema: {
body: Type.Number(),
response: {
200: Type.Number()
}
}
}, (req, res) => wrapper<typeof req, typeof res>((req, res) => {
// handle request
}) as any) // to get around issues resolving the route handler return type Form 3Reduce to expected wrapper pattern. The following will type check, however we've lost the inference for fastify.post('/', {
schema: {
body: Type.Number(),
response: {
200: Type.Number()
}
}
}, wrapper((req, res) => { // req, res are both unknown
// handle request
}) as any) So, based on the above, you can kind of see where things are breaking down, first the route return type, then the req, res inference. Unfortunately, there's not really a trivial way to ensure types propagate correctly without the req, res parameters. There may be something you can do with creating a mapping FastifyRouteHandler type (and deriving req, res through conditional mapping), but would likely run into invariant type issues along the way (and overall the implementation of the type would be quite complex). The general takeaway I guess is that wrapper patterns are generally not supported with Type Providers (with Form 2 about the best you can reduce things currently) Hope this helps |
hi @sinclairzx81, thanks a lot for the great answer, always. 🙏👍 It makes sense. As you said, it seems when TS goes deep into to infer |
@benevbright - have you come up with something yet? I am trying to build a tiny RPC-style wrapper and running into this same issue |
@kevbook unfortunately I dropped it 🙏 |
Prerequisites
Issue
This is more about TS question... sorry about asking it here.
I have a simple Fastify route. my
fastify
is usingfastify.withTypeProvider<TypeBoxTypeProvider>();
I want to create a wrapper for the route handler
This looks simple thing to do but I failed to pass inline function's type to my wrapper's parameter.
I've tried something like below
or
But this doesn't work and not passing inline function's type to my wrapper's parameter function... I know what's wrong here but is there any way to solve my issue?
(I can't use types provided from Fastify because I need type inferring from the schema)
Thanks
The text was updated successfully, but these errors were encountered: