mirror of
https://github.com/honojs/hono.git
synced 2024-11-29 17:46:30 +01:00
feat: Allow context.jsonT
to take interface as an argument (#1162)
This commit is contained in:
parent
aaa1c6d4b9
commit
81d271279c
@ -4,7 +4,7 @@ import type { Env, NotFoundHandler, Input } from './types.ts'
|
||||
import type { CookieOptions } from './utils/cookie.ts'
|
||||
import { serialize } from './utils/cookie.ts'
|
||||
import type { StatusCode } from './utils/http-status.ts'
|
||||
import type { JSONValue } from './utils/types.ts'
|
||||
import type { JSONValue, InterfaceToType } from './utils/types.ts'
|
||||
|
||||
type Runtime = 'node' | 'deno' | 'bun' | 'workerd' | 'fastly' | 'edge-light' | 'lagon' | 'other'
|
||||
type HeaderRecord = Record<string, string | string[]>
|
||||
@ -48,9 +48,40 @@ interface JSONTRespond {
|
||||
object: T extends JSONValue ? T : JSONValue,
|
||||
status?: StatusCode,
|
||||
headers?: HeaderRecord
|
||||
): TypedResponse<T extends JSONValue ? (JSONValue extends T ? never : T) : never>
|
||||
): TypedResponse<
|
||||
InterfaceToType<T> extends JSONValue
|
||||
? JSONValue extends InterfaceToType<T>
|
||||
? never
|
||||
: T
|
||||
: never
|
||||
>
|
||||
<T>(
|
||||
object: InterfaceToType<T> extends JSONValue ? T : JSONValue,
|
||||
status?: StatusCode,
|
||||
headers?: HeaderRecord
|
||||
): TypedResponse<
|
||||
InterfaceToType<T> extends JSONValue
|
||||
? JSONValue extends InterfaceToType<T>
|
||||
? never
|
||||
: T
|
||||
: never
|
||||
>
|
||||
<T>(object: T extends JSONValue ? T : JSONValue, init?: ResponseInit): TypedResponse<
|
||||
T extends JSONValue ? (JSONValue extends T ? never : T) : never
|
||||
InterfaceToType<T> extends JSONValue
|
||||
? JSONValue extends InterfaceToType<T>
|
||||
? never
|
||||
: T
|
||||
: never
|
||||
>
|
||||
<T>(
|
||||
object: InterfaceToType<T> extends JSONValue ? T : JSONValue,
|
||||
init?: ResponseInit
|
||||
): TypedResponse<
|
||||
InterfaceToType<T> extends JSONValue
|
||||
? JSONValue extends InterfaceToType<T>
|
||||
? never
|
||||
: T
|
||||
: never
|
||||
>
|
||||
}
|
||||
|
||||
@ -309,10 +340,16 @@ export class Context<
|
||||
}
|
||||
|
||||
jsonT: JSONTRespond = <T>(
|
||||
object: T extends JSONValue ? T : JSONValue,
|
||||
object: InterfaceToType<T> extends JSONValue ? T : JSONValue,
|
||||
arg?: StatusCode | RequestInit,
|
||||
headers?: HeaderRecord
|
||||
): TypedResponse<T extends JSONValue ? (JSONValue extends T ? never : T) : never> => {
|
||||
): TypedResponse<
|
||||
InterfaceToType<T> extends JSONValue
|
||||
? JSONValue extends InterfaceToType<T>
|
||||
? never
|
||||
: T
|
||||
: never
|
||||
> => {
|
||||
return {
|
||||
response: typeof arg === 'number' ? this.json(object, arg, headers) : this.json(object, arg),
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
|
@ -21,3 +21,5 @@ export type JSONPrimitive = string | boolean | number | null | undefined
|
||||
export type JSONArray = (JSONPrimitive | JSONObject | JSONArray)[]
|
||||
export type JSONObject = { [key: string]: JSONPrimitive | JSONArray | JSONObject }
|
||||
export type JSONValue = JSONObject | JSONArray | JSONPrimitive
|
||||
|
||||
export type InterfaceToType<T> = T extends Function ? T : { [K in keyof T]: InterfaceToType<T[K]> }
|
||||
|
@ -359,6 +359,21 @@ describe('Merge path with `app.route()`', () => {
|
||||
expect(data.ok).toBe(true)
|
||||
})
|
||||
|
||||
it('Should have correct types - with interface', async () => {
|
||||
interface Result {
|
||||
ok: boolean
|
||||
}
|
||||
const result: Result = { ok: true }
|
||||
const base = new Hono<Env>().basePath('/api')
|
||||
const app = base.get('/search', (c) => c.jsonT(result))
|
||||
type AppType = typeof app
|
||||
const client = hc<AppType>('http://localhost')
|
||||
const res = await client.api.search.$get()
|
||||
const data = await res.json()
|
||||
type verify = Expect<Equal<Result, typeof data>>
|
||||
expect(data.ok).toBe(true)
|
||||
})
|
||||
|
||||
it('Should not allow the incorrect JSON type', async () => {
|
||||
const app = new Hono()
|
||||
// @ts-ignore
|
||||
|
@ -4,7 +4,7 @@ import type { Env, NotFoundHandler, Input } from './types'
|
||||
import type { CookieOptions } from './utils/cookie'
|
||||
import { serialize } from './utils/cookie'
|
||||
import type { StatusCode } from './utils/http-status'
|
||||
import type { JSONValue } from './utils/types'
|
||||
import type { JSONValue, InterfaceToType } from './utils/types'
|
||||
|
||||
type Runtime = 'node' | 'deno' | 'bun' | 'workerd' | 'fastly' | 'edge-light' | 'lagon' | 'other'
|
||||
type HeaderRecord = Record<string, string | string[]>
|
||||
@ -48,9 +48,40 @@ interface JSONTRespond {
|
||||
object: T extends JSONValue ? T : JSONValue,
|
||||
status?: StatusCode,
|
||||
headers?: HeaderRecord
|
||||
): TypedResponse<T extends JSONValue ? (JSONValue extends T ? never : T) : never>
|
||||
): TypedResponse<
|
||||
InterfaceToType<T> extends JSONValue
|
||||
? JSONValue extends InterfaceToType<T>
|
||||
? never
|
||||
: T
|
||||
: never
|
||||
>
|
||||
<T>(
|
||||
object: InterfaceToType<T> extends JSONValue ? T : JSONValue,
|
||||
status?: StatusCode,
|
||||
headers?: HeaderRecord
|
||||
): TypedResponse<
|
||||
InterfaceToType<T> extends JSONValue
|
||||
? JSONValue extends InterfaceToType<T>
|
||||
? never
|
||||
: T
|
||||
: never
|
||||
>
|
||||
<T>(object: T extends JSONValue ? T : JSONValue, init?: ResponseInit): TypedResponse<
|
||||
T extends JSONValue ? (JSONValue extends T ? never : T) : never
|
||||
InterfaceToType<T> extends JSONValue
|
||||
? JSONValue extends InterfaceToType<T>
|
||||
? never
|
||||
: T
|
||||
: never
|
||||
>
|
||||
<T>(
|
||||
object: InterfaceToType<T> extends JSONValue ? T : JSONValue,
|
||||
init?: ResponseInit
|
||||
): TypedResponse<
|
||||
InterfaceToType<T> extends JSONValue
|
||||
? JSONValue extends InterfaceToType<T>
|
||||
? never
|
||||
: T
|
||||
: never
|
||||
>
|
||||
}
|
||||
|
||||
@ -309,10 +340,16 @@ export class Context<
|
||||
}
|
||||
|
||||
jsonT: JSONTRespond = <T>(
|
||||
object: T extends JSONValue ? T : JSONValue,
|
||||
object: InterfaceToType<T> extends JSONValue ? T : JSONValue,
|
||||
arg?: StatusCode | RequestInit,
|
||||
headers?: HeaderRecord
|
||||
): TypedResponse<T extends JSONValue ? (JSONValue extends T ? never : T) : never> => {
|
||||
): TypedResponse<
|
||||
InterfaceToType<T> extends JSONValue
|
||||
? JSONValue extends InterfaceToType<T>
|
||||
? never
|
||||
: T
|
||||
: never
|
||||
> => {
|
||||
return {
|
||||
response: typeof arg === 'number' ? this.json(object, arg, headers) : this.json(object, arg),
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
|
@ -21,3 +21,5 @@ export type JSONPrimitive = string | boolean | number | null | undefined
|
||||
export type JSONArray = (JSONPrimitive | JSONObject | JSONArray)[]
|
||||
export type JSONObject = { [key: string]: JSONPrimitive | JSONArray | JSONObject }
|
||||
export type JSONValue = JSONObject | JSONArray | JSONPrimitive
|
||||
|
||||
export type InterfaceToType<T> = T extends Function ? T : { [K in keyof T]: InterfaceToType<T[K]> }
|
||||
|
Loading…
Reference in New Issue
Block a user