zValidator c.req.valid("form") type error
Hey everyone, I am trying to use the zValidator middleware which I have setup in an auth.validator.ts file which looks like:
I have my route setup like:
and signUpController like:
When I am trying to use c.req.valid("form") i get the error:
Argument of type '"form"' is not assignable to parameter of type 'never'.
Im assuming its because the validator middleware is defined in and the route is setup in index.ts.
how do I fix this? Do I have to type the Env being passed into the hono router created in index.ts? If so, how?17 Replies
Figured it out by using a factory
Context
takes three generic arguments. To abstract validation like this, you’d need to specify Input
This level of abstraction conflicts with how Hono is typed/designed. You can do it, but you’ll need to work around it, as you do here
factory.createApp
?the docs discourage RoR-like controllers like yours for the exact issues you are facing
(even though I fail to see how that is a controller, coming from an ASP.NET background)
I used createHandlers:
Do you have a recommendation on best practices?
Best Practices - Hono
Web framework built on Web Standards for Cloudflare Workers, Fastly Compute, Deno, Bun, Vercel, Node.js, and others. Fast, but not only fast.
inline everything until you need to abstract something out
sums it up pretty well
hmm, I see. It felt a lot cleaner to do it in the RoR style. Beside complex typing are there performance complications ?
I think your coding background defines that ngl (not talking about performance lol)
my first backend was in ASP.NET, so controllers for me are way too different from the controllers you imagine
src/controllers/AuthController.ts
src/index.ts
is how I'd shape a controller
and I design my middleware to be idempotent, so I can call them multiple times across multiple controllers w/o care
TL;DR, design your middleware to do the heavy lifting once
I see, would you refactor any of the logic into different files or would everything (validation, data access, view) for auth live in AuthController.ts?
depends
if it has to do with db, I have made a repository for it
if it has to do with validation, I either inline the zod schema, or place it in a separate file, depends on how re-usable the schema is
here is another example of a controller

(I didn't chain everything together cause I don't use the rpc)
new files, or other forms of abstraction, reduce the cognitive load of their context, but increase your app's complexity in other ways
understanding when to abstract something is probably a life-long journey
but in my experience, abstracting something just to follow a pattern, or some idea of how to code, typically hurts more than it helps
it's only when you repeat something a bunch that you start to get an idea of what an abstraction actually needs to accomplish to be useful, in that specific case
I think a combination of KISS and DRY are perfect for hono
Keep It Simple Silly + Don't Repeat Yourself
@Kalpak i think you're right to break out things like
db
and auth
, for example. but they're mostly backend code, and trying to make them entirely self-contained (as you might in node
) isn't in sync with how cloudflare works
your endpoint logic also looks good to me
but abstracting with createHandlers
seems to be adding more complexity to your implementation than it's worthGot it, appreaciate all the detailed responses and help. Thanks!