H
Hono2mo ago
Eternal

`args?` is blank despite using zValidator

Set up details Using Deno (2.4.2, the latest version) And all the other packages are also up-to-date (Hono 4.8.5, zod-validator 0.7.1, Zod 4.0.5) I'm getting the packages from NPM, not JSR Issue Hono client infers the route as $post: (args?: {}, options?: ClientRequestOptions). Notice the blank args?. This is not expected behavior Expected behavior is args: { json: { name: string } } Server Code:
import { Hono } from 'hono'
import { zValidator as baseZodValidator } from '@hono/zod-validator';
import z from 'zod';

let state = {}
const app = new Hono()
.post("/set", baseZodValidator("json", z.object({
name: z.string()
})), (c) => {
const partialState = c.req.valid("json")
state = { ...state, ...partialState }
return c.json(state)
})
.get('/', (c) => {
return c.json(state)
})

Deno.serve(app.fetch)
export type AppType = typeof app
import { Hono } from 'hono'
import { zValidator as baseZodValidator } from '@hono/zod-validator';
import z from 'zod';

let state = {}
const app = new Hono()
.post("/set", baseZodValidator("json", z.object({
name: z.string()
})), (c) => {
const partialState = c.req.valid("json")
state = { ...state, ...partialState }
return c.json(state)
})
.get('/', (c) => {
return c.json(state)
})

Deno.serve(app.fetch)
export type AppType = typeof app
Client code
const globalStateClient = hc<AppType>("localhost:8080")
globalStateClient.set.$post()
const globalStateClient = hc<AppType>("localhost:8080")
globalStateClient.set.$post()
8 Replies
Eternal
EternalOP2mo ago
Please ping me when you respond
blair
blair2mo ago
This works fine for me? main.ts:
import { Hono } from 'hono'
import { zValidator as baseZodValidator } from '@hono/zod-validator';
import z from 'zod';

let state = {}
const app = new Hono()
.post("/set", baseZodValidator("json", z.object({
name: z.string()
})), (c) => {
const partialState = c.req.valid("json")
state = { ...state, ...partialState }
return c.json(state)
})
.get('/', (c) => {
return c.json(state)
})

Deno.serve(app.fetch)
export type AppType = typeof app
import { Hono } from 'hono'
import { zValidator as baseZodValidator } from '@hono/zod-validator';
import z from 'zod';

let state = {}
const app = new Hono()
.post("/set", baseZodValidator("json", z.object({
name: z.string()
})), (c) => {
const partialState = c.req.valid("json")
state = { ...state, ...partialState }
return c.json(state)
})
.get('/', (c) => {
return c.json(state)
})

Deno.serve(app.fetch)
export type AppType = typeof app
client.ts
import type { AppType } from "./main.ts";
import { hc } from "hono/client";

const globalStateClient = hc<AppType>("localhost:8080")
globalStateClient.set.$post();
import type { AppType } from "./main.ts";
import { hc } from "hono/client";

const globalStateClient = hc<AppType>("localhost:8080")
globalStateClient.set.$post();
$ deno check
Check file:///Users/xxx/dev/test/client.ts
Check file:///Users/xxx/dev/test/main.ts
TS2554 [ERROR]: Expected 1-2 arguments, but got 0.
globalStateClient.set.$post();
~~~~~
at file:///Users/xxx/dev/test/client.ts:5:23

An argument for 'args' was not provided.
at file:///Users/xxx/Library/Caches/deno/npm/registry.npmjs.org/hono/4.8.5/dist/types/client/types.d.ts:25:63

error: Type checking failed.
$ deno check
Check file:///Users/xxx/dev/test/client.ts
Check file:///Users/xxx/dev/test/main.ts
TS2554 [ERROR]: Expected 1-2 arguments, but got 0.
globalStateClient.set.$post();
~~~~~
at file:///Users/xxx/dev/test/client.ts:5:23

An argument for 'args' was not provided.
at file:///Users/xxx/Library/Caches/deno/npm/registry.npmjs.org/hono/4.8.5/dist/types/client/types.d.ts:25:63

error: Type checking failed.
With args as {}:
$ deno check
Check file:///Users/xxx/dev/test/client.ts
Check file:///Users/xxx/dev/test/main.ts
TS2345 [ERROR]: Argument of type '{}' is not assignable to parameter of type '{ json: { name: string; }; }'.
Property 'json' is missing in type '{}' but required in type '{ json: { name: string; }; }'.
globalStateClient.set.$post({});
~~
at file:///Users/xxx/dev/test/client.ts:5:29

error: Type checking failed.
$ deno check
Check file:///Users/xxx/dev/test/client.ts
Check file:///Users/xxx/dev/test/main.ts
TS2345 [ERROR]: Argument of type '{}' is not assignable to parameter of type '{ json: { name: string; }; }'.
Property 'json' is missing in type '{}' but required in type '{ json: { name: string; }; }'.
globalStateClient.set.$post({});
~~
at file:///Users/xxx/dev/test/client.ts:5:29

error: Type checking failed.
YAGPDB.xyz
YAGPDB.xyz2mo ago
Above time (05:23 AWST) in your local time
Eternal
EternalOP2mo ago
deno check passes for me
PS C:\Users\Eternal\Code\Deno> deno check

Check file:///C:/Users/Eternal/Code/Deno/client.ts
Check file:///C:/Users/Eternal/Code/Deno/main.ts
Check file:///C:/Users/Eternal/Code/Deno/types.ts
PS C:\Users\Eternal\Code\Deno> deno check

Check file:///C:/Users/Eternal/Code/Deno/client.ts
Check file:///C:/Users/Eternal/Code/Deno/main.ts
Check file:///C:/Users/Eternal/Code/Deno/types.ts
Eternal
EternalOP2mo ago
Intellisense isn't recognizing anything
No description
Eternal
EternalOP2mo ago
Initially, I thought this was the LSP acting up, so I restarted VSCode and I even restarted by computer but it still thinks everything is fine and doesn't infer the type of args properly
blair
blair2mo ago
The intellisense screenshot you show has completely different types - is this intentional? Check the intellisense definition for AppType in both main.ts and client.ts to check if they match, or else something buggy is going on (with ts)
Eternal
EternalOP2mo ago
The differing ClientResponse<> type is intentional I moved parts of the full implementation and just gave you the basic code needed to reproduce the issue, but I used the full implementation in the screenshot Here is the AppType in main.ts of the basic implementation
type AppType = Hono<BlankEnv, {
"/set": {
$post: {
input: {};
output: never;
outputFormat: "json";
status: ContentfulStatusCode;
};
};
} & {
"/": {
$get: {
input: {};
output: never;
outputFormat: "json";
status: ContentfulStatusCode;
};
};
}, "/">
type AppType = Hono<BlankEnv, {
"/set": {
$post: {
input: {};
output: never;
outputFormat: "json";
status: ContentfulStatusCode;
};
};
} & {
"/": {
$get: {
input: {};
output: never;
outputFormat: "json";
status: ContentfulStatusCode;
};
};
}, "/">
Here is the client type of the basic implementation
const globalStateClient: {
index: ClientRequest<{
$get: {
input: {};
output: never;
outputFormat: "json";
status: ContentfulStatusCode;
};
}>;
} & {
set: ClientRequest<{
$post: {
input: {};
output: never;
outputFormat: "json";
status: ContentfulStatusCode;
};
}>;
}
const globalStateClient: {
index: ClientRequest<{
$get: {
input: {};
output: never;
outputFormat: "json";
status: ContentfulStatusCode;
};
}>;
} & {
set: ClientRequest<{
$post: {
input: {};
output: never;
outputFormat: "json";
status: ContentfulStatusCode;
};
}>;
}
The basic implementation has
baseZodValidator("json", z.object({
name: z.string()
}))
baseZodValidator("json", z.object({
name: z.string()
}))
but TypeScript doesn't recognize that and makes args a blank object Weirdly, this issue doesn't happen in another Deno project. Only this Deno project Did I mess something up in my deno.json or tsconfig.json? I removed all the tsconfig.json files in my project and restarted VSCode (closed all windows and reopened them) and the issue with args is still happening Fixed It was Deno acting up Solution Delete all deno.lock Run deno cache --reload on all the important files. The full command I ran was deno cache --reload client.ts main.ts Ta-da! Things are fixed Thanks @blair

Did you find this page helpful?