> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/honojs/hono/llms.txt
> Use this file to discover all available pages before exploring further.

# Client Types

> TypeScript types for the Hono RPC client

## Overview

The Hono client provides several utility types for extracting request and response types from your API endpoints, enabling full type safety in your client code.

## Import

```typescript theme={null}
import type {
  InferRequestType,
  InferResponseType,
  ClientRequestOptions,
  ClientResponse,
  Fetch
} from 'hono/client'
```

## Type Inference Utilities

### InferRequestType

Extracts the request type (arguments) from a client endpoint method.

**Type Signature**:

```typescript theme={null}
type InferRequestType<T> = T extends (
  args: infer R,
  options: any | undefined
) => Promise<ClientResponse<unknown>>
  ? NonNullable<R>
  : never
```

**Usage**:

```typescript theme={null}
import { hc } from 'hono/client'
import type { AppType } from './server'
import type { InferRequestType } from 'hono/client'

const client = hc<AppType>('http://localhost:3000')

// Extract request type for a specific endpoint
type PostsCreateRequest = InferRequestType<typeof client.api.posts.$post>
// Result: { json: { title: string; content: string } }

// Use in function signatures
function createPost(data: PostsCreateRequest) {
  return client.api.posts.$post(data)
}
```

**Example with validation**:

```typescript theme={null}
import { z } from 'zod'
import { zValidator } from '@hono/zod-validator'

// Server route with validation
const route = app.post(
  '/posts',
  zValidator('json', z.object({
    title: z.string(),
    content: z.string(),
    tags: z.array(z.string()).optional()
  })),
  (c) => {
    const data = c.req.valid('json')
    return c.json({ id: '123', ...data })
  }
)

// Client type inference
type CreatePostInput = InferRequestType<typeof client.api.posts.$post>
// Result: { json: { title: string; content: string; tags?: string[] } }
```

### InferResponseType

Extracts the response type from a client endpoint method, with optional status code filtering.

**Type Signature**:

```typescript theme={null}
type InferResponseType<T, StatusCode extends number = StatusCode> = // ...
```

<ParamField path="T" type="endpoint method" required>
  The client endpoint method to infer from
</ParamField>

<ParamField path="StatusCode" type="number" default="any status code">
  Optional status code to filter by. Only returns the response type for matching status codes.
</ParamField>

**Usage**:

```typescript theme={null}
import type { InferResponseType } from 'hono/client'

// Infer response type for any status code
type PostsResponse = InferResponseType<typeof client.api.posts.$get>
// Result: { id: string; title: string; content: string }[]

// Infer response type for specific status code
type PostsSuccess = InferResponseType<typeof client.api.posts.$get, 200>
// Result: { id: string; title: string; content: string }[]

type PostsNotFound = InferResponseType<typeof client.api.posts[':id'].$get, 404>
// Result: { error: string }
```

**Example with multiple response types**:

```typescript theme={null}
// Server route with different responses
app.get('/posts/:id', (c) => {
  const id = c.req.param('id')
  const post = findPost(id)
  
  if (!post) {
    return c.json({ error: 'Not found' }, 404)
  }
  
  return c.json({ id, title: post.title }, 200)
})

// Client type inference
type SuccessResponse = InferResponseType<typeof client.api.posts[':id'].$get, 200>
// Result: { id: string; title: string }

type ErrorResponse = InferResponseType<typeof client.api.posts[':id'].$get, 404>
// Result: { error: string }

type AnyResponse = InferResponseType<typeof client.api.posts[':id'].$get>
// Result: { id: string; title: string } | { error: string }
```

## Client Configuration Types

### ClientRequestOptions

Configuration options for the RPC client, used both at client creation and per-request.

**Type Definition**:

```typescript theme={null}
type ClientRequestOptions<T = unknown> = {
  fetch?: typeof fetch | HonoRequest
  webSocket?: (...args: ConstructorParameters<typeof WebSocket>) => WebSocket
  init?: RequestInit
  buildSearchParams?: BuildSearchParamsFn
} & (keyof T extends never
  ? {
      headers?:
        | Record<string, string>
        | (() => Record<string, string> | Promise<Record<string, string>>)
    }
  : {
      headers: T | (() => T | Promise<T>)
    })
```

<ResponseField name="fetch" type="typeof fetch">
  Custom fetch implementation. Useful for testing with MSW or using node-fetch.
</ResponseField>

<ResponseField name="headers" type="Record<string, string> | (() => Record<string, string> | Promise<Record<string, string>>)">
  Headers to include with requests. Can be static object or async function for dynamic headers.
</ResponseField>

<ResponseField name="init" type="RequestInit">
  Standard `RequestInit` options. Takes highest priority and can override Hono's automatic settings.
</ResponseField>

<ResponseField name="buildSearchParams" type="BuildSearchParamsFn">
  Custom function to serialize query parameters.
</ResponseField>

<ResponseField name="webSocket" type="(...args: ConstructorParameters<typeof WebSocket>) => WebSocket">
  Custom WebSocket constructor.
</ResponseField>

**Usage**:

```typescript theme={null}
import { hc } from 'hono/client'
import type { ClientRequestOptions } from 'hono/client'

const options: ClientRequestOptions = {
  headers: async () => {
    const token = await getAuthToken()
    return { 'Authorization': `Bearer ${token}` }
  },
  init: {
    credentials: 'include'
  }
}

const client = hc('http://localhost:3000', options)
```

### BuildSearchParamsFn

Function type for custom query parameter serialization.

**Type Definition**:

```typescript theme={null}
type BuildSearchParamsFn = (
  query: Record<string, string | string[]>
) => URLSearchParams
```

**Usage**:

```typescript theme={null}
import qs from 'qs'

const buildSearchParams: BuildSearchParamsFn = (query) => {
  // Use bracket notation for arrays: key[]=a&key[]=b
  return new URLSearchParams(qs.stringify(query))
}

const client = hc('http://localhost:3000', {
  buildSearchParams
})
```

## Response Types

### ClientResponse

Type-safe response interface that extends the standard `Response` with inferred types.

**Type Definition**:

```typescript theme={null}
interface ClientResponse<
  T,
  U extends number = StatusCode,
  F extends ResponseFormat = ResponseFormat
> {
  readonly body: ReadableStream | null
  readonly bodyUsed: boolean
  ok: U extends SuccessStatusCode
    ? true
    : U extends Exclude<StatusCode, SuccessStatusCode>
      ? false
      : boolean
  redirected: boolean
  status: U
  statusText: string
  type: 'basic' | 'cors' | 'default' | 'error' | 'opaque' | 'opaqueredirect'
  headers: Headers
  url: string
  redirect(url: string, status: number): Response
  clone(): Response
  bytes(): Promise<Uint8Array<ArrayBuffer>>
  json(): Promise<T>
  text(): Promise<string>
  blob(): Promise<Blob>
  formData(): Promise<FormData>
  arrayBuffer(): Promise<ArrayBuffer>
}
```

<ResponseField name="T" type="generic">
  The response body type (inferred from server route)
</ResponseField>

<ResponseField name="U" type="number">
  The HTTP status code
</ResponseField>

<ResponseField name="F" type="ResponseFormat">
  The response format ('json', 'text', etc.)
</ResponseField>

**Key Features**:

* The `ok` property type is narrowed based on status code
* The `json()` method returns `Promise<T>` with the inferred response type
* The `text()` method returns `Promise<string>` (or `Promise<T>` for text responses)

**Usage**:

```typescript theme={null}
const response = await client.api.posts.$get()

// Type-safe property access
if (response.ok) {
  // TypeScript knows this is a success response
  const data = await response.json() // Type is inferred
}

// Check status
if (response.status === 404) {
  const error = await response.json() // Error type
}
```

### FilterClientResponseByStatusCode

Filters a `ClientResponse` type to only include specific status codes.

**Type Definition**:

```typescript theme={null}
type FilterClientResponseByStatusCode<
  T extends ClientResponse<any, any, any>,
  U extends number = StatusCode
> = T extends ClientResponse<infer RT, infer RC, infer RF>
  ? RC extends U
    ? ClientResponse<RT, RC, RF>
    : never
  : never
```

**Usage**:

```typescript theme={null}
import type { FilterClientResponseByStatusCode } from 'hono/client'

type AllResponses = ClientResponse<Data, 200 | 404, 'json'>

type SuccessOnly = FilterClientResponseByStatusCode<AllResponses, 200>
// Result: ClientResponse<Data, 200, 'json'>

type ErrorsOnly = FilterClientResponseByStatusCode<AllResponses, 404>
// Result: ClientResponse<Data, 404, 'json'>
```

## Fetch Type

A helper type for creating functions that wrap client endpoints.

**Type Definition**:

```typescript theme={null}
type Fetch<T> = (
  args?: InferRequestType<T>,
  opt?: ClientRequestOptions
) => Promise<ClientResponseOfEndpoint<InferEndpointType<T>>>
```

**Usage**:

```typescript theme={null}
import type { Fetch } from 'hono/client'

// Create a typed wrapper function
function createPostWrapper(client: ReturnType<typeof hc<AppType>>) {
  const endpoint = client.api.posts.$post
  
  const createPost: Fetch<typeof endpoint> = async (args, options) => {
    // Add custom logic before/after
    console.log('Creating post...', args)
    const response = await endpoint(args, options)
    console.log('Response:', response.status)
    return response
  }
  
  return createPost
}
```

## Advanced Types

### ApplyGlobalResponse

Applies global response definitions to your Hono app type.

**Type Definition**:

```typescript theme={null}
type ApplyGlobalResponse<App, Def extends GlobalResponseDefinition> = // ...

type GlobalResponseDefinition = {
  [S in StatusCode]?: {
    [F in KnownResponseFormat]?: unknown
  }
}
```

**Usage**:

```typescript theme={null}
import type { ApplyGlobalResponse } from 'hono/client'

// Define global error responses
type GlobalErrors = {
  404: { json: { error: 'Not found' } }
  500: { json: { error: 'Internal server error' } }
}

type AppWithErrors = ApplyGlobalResponse<typeof app, GlobalErrors>

const client = hc<AppWithErrors>('http://localhost:3000')
```

## Complete Example

Here's a complete example using all the main client types:

```typescript theme={null}
import { hc } from 'hono/client'
import type {
  InferRequestType,
  InferResponseType,
  ClientRequestOptions
} from 'hono/client'
import type { AppType } from './server'

// Configure client with options
const options: ClientRequestOptions = {
  headers: async () => ({
    'Authorization': `Bearer ${await getToken()}`
  })
}

const client = hc<AppType>('http://localhost:3000', options)

// Extract types
type CreatePostInput = InferRequestType<typeof client.api.posts.$post>
type CreatePostOutput = InferResponseType<typeof client.api.posts.$post, 201>
type CreatePostError = InferResponseType<typeof client.api.posts.$post, 400>

// Create type-safe wrapper functions
async function createPost(input: CreatePostInput): Promise<CreatePostOutput> {
  const response = await client.api.posts.$post(input)
  
  if (!response.ok) {
    throw new Error('Failed to create post')
  }
  
  return response.json()
}

// Use the function
const newPost = await createPost({
  json: {
    title: 'Hello Hono',
    content: 'This is type-safe!'
  }
})

console.log(newPost.id, newPost.title) // Fully typed!
```
