Skip to content

Cannot use imported v4 schema in createRoute #1412

@kotkoroid

Description

@kotkoroid

Which middleware has the bug?

@hono/zod-openapi

What version of the middleware?

1.1.0

What version of Hono are you using?

4.9.2

What runtime/platform is your app running on? (with version if possible)

Cloudflare Workers

What steps can reproduce the bug?

Consider a following schema to be imported from a library:

export const paginationSchema = new z.$ZodObject({
  type: 'object',
  shape: {
    page: new z.$ZodDefault({
      type: 'default',
      innerType: new z.$ZodNumber({
        type: 'number',
      }),
      defaultValue: () => 1,
    }),
    limit: new z.$ZodDefault({
      type: 'default',
      innerType: new z.$ZodNumber({
        type: 'number',
      }),
      defaultValue: () => 20,
    }),
  },
})

The library defined the schema using zod/v4/core, following the guidance in Zod docs. However, these core schemas don't have parsing methods like .parse() and .safeParse(). This raises a problem when trying to use the schema directly in createRoute function as it expects full Zod schema with all the parsing methods.

What is the expected behavior?

Basically, I'm stuck between two incompatible approaches: the library correctly follows Zod v4 patterns, but Hono's type system can't work with those patterns. I either have to recreate the entire schema myself, which defeats the purpose of using the library, or I lose all type safety in my route handlers. It seems like there should be a way to bridge these two approaches without sacrificing either reusability or type safety.

What do you see instead?

I tried creating a wrapper function that adds the parsing methods to the core schema, which lets me create the route successfully:

function withMethods<T extends zCore.$ZodObject>(coreSchema: T) {
  const methods = {
    parse: (data: unknown) => zCore.parse(coreSchema, data),
    safeParse: (data: unknown) => zCore.safeParse(coreSchema, data),
    parseAsync: (data: unknown) => zCore.parseAsync(coreSchema, data),
    safeParseAsync: (data: unknown) => zCore.safeParseAsync(coreSchema, data),
  }

  return Object.assign(Object.create(Object.getPrototypeOf(coreSchema)), {
    ...coreSchema,
    ...methods,
    _output: undefined as zCore.infer<T>,
  })
}

However, when I try to use the route handler with proper types, the inference completely breaks down as RouteHandler type can't figure out what the query parameters should be:

const { limit } = context.req.valid('query') // Argument of type '"query"' is not assignable to parameter of type 'never'. (ts 2345)

Additional information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions