MiddlewareHandler response type inference
What is the feature you are proposing?
When we use middleware, it can return a Response object or a Typed Response, for example, @hono/validator returns a MiddlewareHandler that can return a response with a 400 status code.
The validator function returns a middleware handler type with a probably response returning type:
But then, if we use a validator or custom middleware that returns a response object, Hono can't infer the returning type for the Hono instance, and RPC also. Example from official docs:
We can see that hono infer only 201 response status code. And we can't see 400 code that return zValidator in middleware.
We can also create a custom validator and see the same thing - in the validator we return the 400 code, but we don't see it in the types:
So we can't handle error if status code === 400.
We can solve this by using the res.status() method before returning the res.json() and get "StatusCode" type in statusCode field.
But I think that's not how it's supposed to work.
So I've go in types.ts file in source code of Hono.dev and start working on type inference for MiddlewareHandlers.
You can see what I have come up with in the my fork of Hono GitHub Repo. However, I have gotten stuck and am still unable to make progress with type inference from the validator function, as well as with type inference for functions such as app.get(...handlers: H[]), in the HandlerInterface.
This has been brought a few times before, #2719, #580, #3170. The devs seem to be aware of it but sadly don't think there's been any update in about 6 months.
This has been brought a few times before, #2719, #580, #3170. The devs seem to be aware of it but sadly don't think there's been any update in about 6 months.
So now the only way to get around the typing error in rpc is to use c.status() before returning the response, like in my example?
If you use Zod OpenAPI, you can explicitly set the possible return types like this:
export const listingRoute = router
.openapi(
createRoute({
middleware: [authMiddleware] as const,
path: "/",
method: "get",
tags: ["Listings"],
description: "Get all listings",
responses: {
[HttpStatusCodes.OK]: {
content: {
"application/json": {
schema: ListingSchema.array(),
},
},
description: "Successfully retrieved all listings",
},
[HttpStatusCodes.UNAUTHORIZED]: {
content: {
"application/json": {
schema: z.object({
message: z.string(),
}),
},
},
description: "Unauthorized",
},
},
}),
async (c) => {
const listings = await prisma.listing.findMany();
return c.json(listings, HttpStatusCodes.OK);
},
)
The type gets inferred correctly:
This is definitely a much needed addition