使用Hono Zod验证中间件时遭遇类型安全问题求助
Hono Zod验证中间件类型安全问题解决方案
问题场景
我在Hono中使用Zod和@hono/zod-validator实现验证中间件,代码如下:
const validationMiddleware = (schema: ZodSchema, target: keyof ValidationTargets) => { return createMiddleware(async (c, next) => { await next() zValidator(target, schema, (result, c) => { if (!result.success) { return c.json({ success: false, error: { code: 400, message: result.error.issues[0].message, innerError: { timestamp: new Date(Date.now()) } } }) } }) }) }
调用方式:
validationMiddleware(userValidation, 'json')
使用c.req.valid('json')时TypeScript抛出错误:
TS2345: Argument of type string is not assignable to parameter of type never on the 'json' input
TypeScript将参数类型推断为never,无法获得预期的类型安全支持。
问题根源
- 执行顺序错误:先调用
await next()会让路由逻辑先于验证执行,不仅逻辑颠倒,还打断了Hono的类型推断链,导致框架无法识别该目标已被验证。 - 类型信息缺失:中间件没有通过泛型传递Zod Schema的类型信息,Hono无法关联验证目标和对应的类型。
修复方案
1. 修正中间件执行逻辑
先执行验证,验证通过后再进入后续路由/中间件:
import { createMiddleware } from 'hono' import { zValidator } from '@hono/zod-validator' import type { ZodSchema, ValidationTargets } from 'hono' const validationMiddleware = <T extends ZodSchema>( schema: T, target: keyof ValidationTargets ) => { return createMiddleware(async (c, next) => { // 先执行验证逻辑,再推进到下一个环节 await zValidator(target, schema, (result, c) => { if (!result.success) { return c.json({ success: false, error: { code: 400, message: result.error.issues[0].message, innerError: { timestamp: new Date(Date.now()) } } }, 400) // 显式指定400状态码更规范 } })(c, next) }) }
2. 添加泛型捕获Schema类型
通过泛型<T extends ZodSchema>捕获传入的Schema类型,让Hono的类型系统能正确关联验证目标和对应的类型。
3. 验证类型安全效果
在路由中使用中间件后,c.req.valid('json')会自动推断出Schema对应的类型:
// 示例Zod Schema import { z } from 'zod' const userValidation = z.object({ username: z.string().min(3), email: z.string().email() }) // 路由中使用中间件 app.post('/users', validationMiddleware(userValidation, 'json'), (c) => { // 此处c.req.valid('json')类型自动推断为{ username: string; email: string } const validUser = c.req.valid('json') return c.json({ success: true, data: validUser }) })
内容的提问来源于stack exchange,提问作者hantoren
相关产品推荐
相关产品推荐

