feat(zod-validator): surface the default 400 on the no-hook overload and keep the return assignable to MiddlewareHandler (#1881)
* fix(zod-validator): surface the default 400 failure response on the no-hook overload When `zValidator(target, schema)` is used without a hook, the implementation falls through to `c.json(result, 400)` on validation failure, but the declared return type was `MiddlewareHandler<E, P, V>` (R defaults to `Response`). As a result, `MergeMiddlewareResponse<M_k>` in honojs/hono extracted only `Response`, which `ExtractTypedResponseOnly<Response>` maps to `never`, and the failing 400 never reached the RPC schema. Add `ZodValidatorFailureBody<T>` (the failure variant of `safeParseAsync`'s result, supporting both Zod v3 and v4) and widen the no-hook overload to `MiddlewareHandler<E, P, V, TypedResponse<ZodValidatorFailureBody<T>, 400, 'json'>>`. Combined with honojs/hono#4393 and #4906, the failure response now flows through to `hc<typeof app>` so clients can narrow `res.status === 400` and read the typed `SafeParseError` body. The with-hook overload is left unchanged to avoid introducing a phantom JSON 400 entry for callers whose hook always returns its own response; they continue to opt in via `ExtractValidationResponse<HookFn>`. Refs: honojs/hono#3746 * fix(zod-validator): make zValidator return type assignable to a generic MiddlewareHandler ExtractValidationResponse and ZodValidatorFailureResponse returned bare TypedResponse<...> values, which do not extend Response. Assigning a zValidator middleware to a plain MiddlewareHandler therefore failed with TS2322. Intersect both with Response (Response & TypedResponse<...>) so the no-hook and with-hook paths are symmetrically assignable. Also: - Collapse the two no-hook overloads into a single signature taking `hook?: undefined` - Extract the options parameter shape into ValidationFunctionOption<T, Target> - Add generic-MiddlewareHandler assignment tests to the Basic and With Hook describes for both v3 and v4 - Update the changeset to describe the full set of zod-validator changes * fix(zod-validator): bump peerDependencies.hono to >=4.10.0 The no-hook overload returns MiddlewareHandler with four type arguments, which only exists from hono v4.10.0. The RPC inference pipeline (ExtractHandlerResponse / MergeMiddlewareResponse) that consumes the fourth argument is also new in 4.10.0, so older peers cannot surface the typed 400 branch through hc<typeof app>. Verified by running tsc against the PR sources: - hono@4.10.0: clean - hono@4.9.9: TS2707 "MiddlewareHandler requires between 0 and 3 type arguments" * fix(zod-openapi): bump peerDependencies.hono to >=4.10.0 @hono/zod-openapi has @hono/zod-validator as a direct dependency, so its peer range must be at least as strict as zod-validator's. After zod-validator's peerDependencies.hono was bumped to >=4.10.0 for the typed-400 fix, leaving zod-openapi at >=4.3.6 lets users install it against e.g. hono@4.9.9, where the bundled zod-validator types reference the 4-argument MiddlewareHandler<E, P, I, R> (new in Hono v4.10.0) and fail to compile. Reproduced the cascade in a sandbox with hono@4.9.9: - npm install: ERESOLVE peer dep conflict - tsc (after --legacy-peer-deps): TS2707 from node_modules/@hono/zod-validator/dist/index.d.ts * chore: update lockfile * fix(zod-openapi): update changeset bump level to minor * fix(zod-validator): update changeset bump level to minor
T
tako._.v committed
e90e4fb30877f3e3f4b0588bdb2bbfc337efbf67
Parent: 0d88669
Committed by GitHub <noreply@github.com>
on 5/9/2026, 10:17:44 AM