You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Hono与Zod创建通用路由时遇TypeScript类型错误

解决Hono抽离路由处理函数后的TypeScript类型错误

这个错误不是bug,是你抽离函数时没给Context指定正确的类型,导致TypeScript无法推断出c.json()的合法参数类型,才抛出"never"类型的错误。

错误场景还原

你大概率写了类似这样的代码:

import { Hono } from 'hono'
import { z } from 'zod'
import { zValidator } from '@hono/zod-validator'

const app = new Hono()

// 抽离的处理函数,没指定Context类型
const handleGetUser = (c) => {
  const { id } = c.req.valid('param')
  // 这里会报错:Argument of type '"json"' is not assignable to parameter of type 'never'
  return c.json({ id, name: 'Shahriar' })
}

app.get('/users/:id', zValidator('param', z.object({ id: z.string() })), handleGetUser)

解决方法

给抽离的处理函数的参数c指定包含校验后参数类型的Hono Context即可,有两种常用写法:

写法一:手动定义Context类型

import { Hono, Context } from 'hono'
import { z } from 'zod'
import { zValidator } from '@hono/zod-validator'

const app = new Hono()

// 先定义参数校验的Schema
const UserParamSchema = z.object({ id: z.string() })
// 定义包含参数类型的Context
type UserContext = Context<{
  Param: z.infer<typeof UserParamSchema>
}>

// 给处理函数指定Context类型
const handleGetUser = (c: UserContext) => {
  const { id } = c.req.valid('param')
  return c.json({ id, name: 'Shahriar' })
}

app.get('/users/:id', zValidator('param', UserParamSchema), handleGetUser)

写法二:使用Hono自带的RouteHandler类型

import { Hono, RouteHandler } from 'hono'
import { z } from 'zod'
import { zValidator } from '@hono/zod-validator'

const app = new Hono()

const UserParamSchema = z.object({ id: z.string() })

// 用RouteHandler指定参数类型
const handleGetUser: RouteHandler<{
  Param: z.infer<typeof UserParamSchema>
}> = (c) => {
  const { id } = c.req.valid('param')
  return c.json({ id, name: 'Shahriar' })
}

app.get('/users/:id', zValidator('param', UserParamSchema), handleGetUser)

原因解释

内联处理函数时,Hono的TypeScript类型系统会自动从路由的中间件(比如zValidator)推断出Context的完整类型,包括req.valid()返回的参数类型和json()方法的合法参数类型。但抽离成独立函数后,TypeScript无法自动关联路由的类型信息,只能把c推断成最宽泛的未知类型,导致方法的类型丢失,最终出现"never"类型错误。

通用路由生成函数的优化

如果要做通用的路由生成工具,可以用泛型封装,让类型自动推断:

import { Hono, Context } from 'hono'
import { z, ZodSchema } from 'zod'
import { zValidator } from '@hono/zod-validator'

const app = new Hono()

// 通用路由生成函数
function createGetRoute<ParamSchema extends ZodSchema>(
  path: string,
  paramSchema: ParamSchema,
  handler: (c: Context<{ Param: z.infer<ParamSchema> }>) => ReturnType<Context['json']>
) {
  app.get(path, zValidator('param', paramSchema), handler)
}

// 使用示例
createGetRoute('/users/:id', z.object({ id: z.string() }), (c) => {
  const { id } = c.req.valid('param')
  return c.json({ id, name: 'Shahriar' })
})

内容的提问来源于stack exchange,提问作者Shahriar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 15:22:43