Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[zod-validator] c.req.valid("json") returning never #77

Closed
geelen opened this issue Mar 31, 2023 · 5 comments
Closed

[zod-validator] c.req.valid("json") returning never #77

geelen opened this issue Mar 31, 2023 · 5 comments

Comments

@geelen
Copy link

geelen commented Mar 31, 2023

Taking the example from the README:

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

const app = new Hono();

const schema = z.object({
  name: z.string(),
  age: z.number(),
});

app.post("/author", zValidator("json", schema), (c) => {
  const data = c.req.valid("json");
  return c.json({
    success: true,
    message: `${data.name} is ${data.age}`,
  });
});

Gives me this error:

src/example.ts:16:22 - error TS2339: Property 'name' does not exist on type 'never'.

16     message: `${data.name} is ${data.age}`,
                        ~~~~

src/example.ts:16:38 - error TS2339: Property 'age' does not exist on type 'never'.

16     message: `${data.name} is ${data.age}`,
                                        ~~~

Not sure what I'm doing wrong, my tsconfig is pretty minimal:

{
  "compilerOptions": {
    "target": "esnext",
    "module": "esnext",
    "lib": ["esnext"],
    "types": ["@cloudflare/workers-types/2022-11-30"],
    "moduleResolution": "node"
  },
  "include": ["src/**/*.ts"]
}
@geelen
Copy link
Author

geelen commented Mar 31, 2023

I can fix it temporarily by changing line 13 to:

const data: z.infer<typeof schema> = c.req.valid("json");

But I'm curious why the inference isn't working correctly. Any ideas?

@yusukebe
Copy link
Member

Hi @geelen !

Try the following two:

  1. Add "strict": true to tsconfig.json.
  2. Use the latest "hono" and "@hono/zod-validator".

@geelen
Copy link
Author

geelen commented Apr 1, 2023

Wow, "strict": true fixed it immediately. Thanks!

@dextermb
Copy link

dextermb commented Jan 16, 2024

Hey @yusukebe, I've got a similar problem to this but I've already got "strict":true in my tsconfig.json.

Here's what I'm working with.

api/routes/auth.ts
import { zValidator } from '@hono/zod-validator'
import { Context, Hono } from 'hono'
import { z } from 'zod'

export const loginSchema = z.object({
  email: z.string().email()
})

export function login (ctx: Context) {
  const data: z.infer<typeof loginSchema> = ctx.req.valid('json')
  //                                                      ^-- "json": Argument of type 'string' is
  //                                                          not assignable to parameter of type
  //                                                          'never'

  return ctx.json(undefined, 202)
}

const auth = new Hono()

auth.post('/', zValidator('json', loginSchema), login)

export default auth
tsconfig.json
{
  "compilerOptions": {
    "baseUrl": "./",
    "target": "ESNext",
    "module": "ESNext",
    "moduleResolution": "node",
    "esModuleInterop": true,
    "skipLibCheck": true,
    "strict": true,
    "allowJs": true,
    "paths": {
      "@/*": [
        "./*"
      ],
      "@service/*": [
        "./services/*"
      ],
      "@route/*": [
        "./api/routes/*"
      ]
    }
  },
  "include": [
    "api",
    "services",
    "global.d.ts",
    "drizzle.config.ts"
  ]
}

Edit: I thought I'd include my .eslintrc.json as well

.eslintrc.json { "settings": { "@typescript-eslint/parser": { "parserOptions": { "project": "./tsconfig.json" } }, "import/resolver": { "typescript": {} } }, "parser": "@typescript-eslint/parser", "parserOptions": { "project": "./tsconfig.json", "tsconfigRootDir": "./" }, "plugins": [ "@typescript-eslint", "drizzle" ], "extends": [ "plugin:@typescript-eslint/recommended", "plugin:import/recommended" ] }

@yusukebe
Copy link
Member

@dextermb

The problem is that the handler is created separately from the application.

https://hono.dev/guides/best-practices#factory-createhandlers-in-hono-factory

You can use the factory method:

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

export const loginSchema = z.object({
  email: z.string().email(),
})

const factory = new Factory()

export const login = factory.createHandlers(zValidator('json', loginSchema), (c) => {
  const data = c.req.valid('json')
  // ...
  return c.json(undefined, 202)
})

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants