diff --git a/deno_dist/validator/validator.ts b/deno_dist/validator/validator.ts index c3ae22ad..f445e0c0 100644 --- a/deno_dist/validator/validator.ts +++ b/deno_dist/validator/validator.ts @@ -29,13 +29,22 @@ export const validator = < M extends string, U extends ValidationTargetByMethod, OutputType = ValidationTargets[U], + OutputTypeExcludeResponseType = ExcludeResponseType, P2 extends string = P, V extends { - in: { [K in U]: unknown extends InputType ? OutputType : InputType } - out: { [K in U]: ExcludeResponseType } + in: { + [K in U]: K extends 'json' + ? InputType + : { [K2 in keyof OutputTypeExcludeResponseType]: ValidationTargets[K][K2] } + } + out: { [K in U]: OutputTypeExcludeResponseType } } = { - in: { [K in U]: unknown extends InputType ? OutputType : InputType } - out: { [K in U]: ExcludeResponseType } + in: { + [K in U]: K extends 'json' + ? InputType + : { [K2 in keyof OutputTypeExcludeResponseType]: ValidationTargets[K][K2] } + } + out: { [K in U]: OutputTypeExcludeResponseType } }, // eslint-disable-next-line @typescript-eslint/no-explicit-any E extends Env = any diff --git a/src/client/client.test.ts b/src/client/client.test.ts index de6c9e6d..63c22334 100644 --- a/src/client/client.test.ts +++ b/src/client/client.test.ts @@ -322,8 +322,8 @@ describe('Infer the response/request type', () => { type Actual = InferRequestType type Expected = { - age: string - name: string + age: string | string[] + name: string | string[] } type verify = Expect> }) diff --git a/src/validator/validator.test.ts b/src/validator/validator.test.ts index b7a2b49e..4c28f3b9 100644 --- a/src/validator/validator.test.ts +++ b/src/validator/validator.test.ts @@ -602,7 +602,7 @@ it('With path parameters', () => { $put: { input: { form: { - title: string + title: string | File } } & { param: { @@ -646,11 +646,11 @@ it('`on`', () => { $purge: { input: { form: { - tag: string + tag: string | File } } & { query: { - q: string + q: string | string[] } } output: { @@ -834,3 +834,39 @@ describe('Validator with using Zod directly', () => { ) }) }) + +describe('Transform', () => { + it('Should be number when the type is transformed', () => { + const route = new Hono().get( + '/', + validator('query', async () => { + return { + page: 1, + } + }), + (c) => { + const { page } = c.req.valid('query') + expectTypeOf(page).toEqualTypeOf() + return c.json({ page }) + } + ) + + type Expected = { + '/': { + $get: { + input: { + query: { + page: string | string[] + } + } + output: { + page: number + } + } + } + } + + type Actual = ExtractSchema + type verify = Expect> + }) +}) diff --git a/src/validator/validator.ts b/src/validator/validator.ts index 52f6b80d..1730192e 100644 --- a/src/validator/validator.ts +++ b/src/validator/validator.ts @@ -29,13 +29,22 @@ export const validator = < M extends string, U extends ValidationTargetByMethod, OutputType = ValidationTargets[U], + OutputTypeExcludeResponseType = ExcludeResponseType, P2 extends string = P, V extends { - in: { [K in U]: unknown extends InputType ? OutputType : InputType } - out: { [K in U]: ExcludeResponseType } + in: { + [K in U]: K extends 'json' + ? InputType + : { [K2 in keyof OutputTypeExcludeResponseType]: ValidationTargets[K][K2] } + } + out: { [K in U]: OutputTypeExcludeResponseType } } = { - in: { [K in U]: unknown extends InputType ? OutputType : InputType } - out: { [K in U]: ExcludeResponseType } + in: { + [K in U]: K extends 'json' + ? InputType + : { [K2 in keyof OutputTypeExcludeResponseType]: ValidationTargets[K][K2] } + } + out: { [K in U]: OutputTypeExcludeResponseType } }, // eslint-disable-next-line @typescript-eslint/no-explicit-any E extends Env = any