Repository: honojs/hono
File: deno_dist/context.ts (TypeScript)

Code before:
}

type ContextOptions<E extends Env> = {
  env: E['Bindings']
  executionCtx?: FetchEvent | ExecutionContext | undefined
  notFoundHandler?: NotFoundHandler<E>
  path?: string
  params?: Record<string, string>
}

export class Context<
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  E extends Env = any,
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  P extends string = any,
  I extends Input = {}
> {
  env: E['Bindings'] = {}
  finalized: boolean = false
  error: Error | undefined = undefined

  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  private _req?: HonoRequest<any, any>
  private _status: StatusCode = 200
  private _exCtx: FetchEvent | ExecutionContext | undefined // _executionCtx
  private _pre: boolean = false // _pretty
  private _preS: number = 2 // _prettySpace
  private _map: Record<string, unknown> | undefined
  private _h: Headers | undefined = undefined //  _headers
  private _pH: Record<string, string> | undefined = undefined // _preparedHeaders
  private _res: Response | undefined
  private _path: string = '/'
  private _params?: Record<string, string> | null
  private rawRequest?: Request | null
  private notFoundHandler: NotFoundHandler<E> = () => new Response()

  constructor(req: Request, options?: ContextOptions<E>) {
    this.rawRequest = req
    if (options) {
      this._exCtx = options.executionCtx
      this._path = options.path ?? '/'
      this._params = options.params
      this.env = options.env
      if (options.notFoundHandler) {
        this.notFoundHandler = options.notFoundHandler
      }
    }
  }

  get req(): HonoRequest<P, I['out']> {
    if (this._req) {

Review comment (suggestion):
I had to add overloads for `JSONTRespond` to avoid breaking existing test cases.
(I had to define both `object: T extends JSONValue ? T : JSONValue` and `object: InterfaceToType<T> extends JSONValue ? T : JSONValue` versions.)

Otherwise, value types like `{ ok: true }` are automatically handled as `{ ok: boolean }`.

Code after:
    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<
    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
  >
}

interface HTMLRespond {
  (html: string, status?: StatusCode, headers?: HeaderRecord): Response
  (html: string, init?: ResponseInit): Response
}

type ContextOptions<E extends Env> = {
  env: E['Bindings']
  executionCtx?: FetchEvent | ExecutionContext | undefined
  notFoundHandler?: NotFoundHandler<E>
  path?: string
  params?: Record<string, string>
}

export class Context<
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  E extends Env = any,
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  P extends string = any,
  I extends Input = {}
> {
  env: E['Bindings'] = {}
  finalized: boolean = false
  error: Error | undefined = undefined