hono icon indicating copy to clipboard operation
hono copied to clipboard

MiddlewareHandler response type inference

Open FOZERY opened this issue 1 year ago • 4 comments

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: image

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: image 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: image

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. image

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.

FOZERY avatar Dec 12 '24 20:12 FOZERY

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.

lewisedc avatar Dec 13 '24 20:12 lewisedc

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?

FOZERY avatar Dec 14 '24 08:12 FOZERY

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:

image

aabuhijleh avatar Dec 20 '24 22:12 aabuhijleh

This is definitely a much needed addition

marsian83 avatar Apr 19 '25 12:04 marsian83