diff --git a/deno_dist/context.ts b/deno_dist/context.ts index 39fd4c573..1f4e6b3e3 100644 --- a/deno_dist/context.ts +++ b/deno_dist/context.ts @@ -6,7 +6,7 @@ import { serialize } from './utils/cookie.ts' import { resolveStream } from './utils/html.ts' import type { StatusCode } from './utils/http-status.ts' import { StreamingApi } from './utils/stream.ts' -import type { JSONValue, InterfaceToType } from './utils/types.ts' +import type { JSONValue, InterfaceToType, JSONParsed } from './utils/types.ts' type HeaderRecord = Record type Data = string | ArrayBuffer | ReadableStream @@ -57,7 +57,7 @@ interface JSONRespond { InterfaceToType extends JSONValue ? JSONValue extends InterfaceToType ? never - : T + : JSONParsed : never > (object: InterfaceToType extends JSONValue ? T : JSONValue, init?: ResponseInit): Response & @@ -65,7 +65,7 @@ interface JSONRespond { InterfaceToType extends JSONValue ? JSONValue extends InterfaceToType ? never - : T + : JSONParsed : never > } @@ -308,7 +308,7 @@ export class Context< InterfaceToType extends JSONValue ? JSONValue extends InterfaceToType ? never - : T + : JSONParsed : never > => { const body = JSON.stringify(object) diff --git a/deno_dist/utils/types.ts b/deno_dist/utils/types.ts index 3767eb93e..5f4bce203 100644 --- a/deno_dist/utils/types.ts +++ b/deno_dist/utils/types.ts @@ -25,8 +25,11 @@ export type IntersectNonAnyTypes = T extends [infer Head, ...in export type JSONPrimitive = string | boolean | number | null | undefined export type JSONArray = (JSONPrimitive | JSONObject | JSONArray)[] -export type JSONObject = { [key: string]: JSONPrimitive | JSONArray | JSONObject } +export type JSONObject = { [key: string]: JSONPrimitive | JSONArray | JSONObject | object } export type JSONValue = JSONObject | JSONArray | JSONPrimitive +export type JSONParsed = { + [k in keyof T]: T[k] extends JSONValue ? T[k] : string +} export type InterfaceToType = T extends Function ? T : { [K in keyof T]: InterfaceToType } diff --git a/src/client/client.test.ts b/src/client/client.test.ts index 59d52b9da..3888c6241 100644 --- a/src/client/client.test.ts +++ b/src/client/client.test.ts @@ -500,15 +500,14 @@ describe('Merge path with `app.route()`', () => { expect(data.ok).toBe(true) }) - it('Should not allow the incorrect JSON type', async () => { + it('Should allow a Date object and return it as a string', async () => { const app = new Hono() - // @ts-expect-error const route = app.get('/api/foo', (c) => c.json({ datetime: new Date() })) type AppType = typeof route const client = hc('http://localhost') const res = await client.api.foo.$get() - const data = await res.json() - type verify = Expect> + const { datetime } = await res.json() + type verify = Expect> }) describe('Multiple endpoints', () => { diff --git a/src/context.ts b/src/context.ts index 895eecc23..8593a82d7 100644 --- a/src/context.ts +++ b/src/context.ts @@ -6,7 +6,7 @@ import { serialize } from './utils/cookie' import { resolveStream } from './utils/html' import type { StatusCode } from './utils/http-status' import { StreamingApi } from './utils/stream' -import type { JSONValue, InterfaceToType } from './utils/types' +import type { JSONValue, InterfaceToType, JSONParsed } from './utils/types' type HeaderRecord = Record type Data = string | ArrayBuffer | ReadableStream @@ -57,7 +57,7 @@ interface JSONRespond { InterfaceToType extends JSONValue ? JSONValue extends InterfaceToType ? never - : T + : JSONParsed : never > (object: InterfaceToType extends JSONValue ? T : JSONValue, init?: ResponseInit): Response & @@ -65,7 +65,7 @@ interface JSONRespond { InterfaceToType extends JSONValue ? JSONValue extends InterfaceToType ? never - : T + : JSONParsed : never > } @@ -308,7 +308,7 @@ export class Context< InterfaceToType extends JSONValue ? JSONValue extends InterfaceToType ? never - : T + : JSONParsed : never > => { const body = JSON.stringify(object) diff --git a/src/utils/types.ts b/src/utils/types.ts index 3767eb93e..5f4bce203 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -25,8 +25,11 @@ export type IntersectNonAnyTypes = T extends [infer Head, ...in export type JSONPrimitive = string | boolean | number | null | undefined export type JSONArray = (JSONPrimitive | JSONObject | JSONArray)[] -export type JSONObject = { [key: string]: JSONPrimitive | JSONArray | JSONObject } +export type JSONObject = { [key: string]: JSONPrimitive | JSONArray | JSONObject | object } export type JSONValue = JSONObject | JSONArray | JSONPrimitive +export type JSONParsed = { + [k in keyof T]: T[k] extends JSONValue ? T[k] : string +} export type InterfaceToType = T extends Function ? T : { [K in keyof T]: InterfaceToType }