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

# Type Safety

> Get full TypeScript type safety with generics for request and response types

ofetch provides excellent TypeScript support with generic types for type-safe API calls.

## Response Type Inference

Use TypeScript generics to specify the expected response type:

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

interface User {
  id: number
  name: string
  email: string
}

// Response is typed as User
const user = await ofetch<User>('https://api.example.com/user/123')

console.log(user.name)  // ✅ TypeScript knows this is a string
console.log(user.age)   // ❌ Error: Property 'age' does not exist
```

## Nested Response Types

For APIs that wrap data in a response envelope:

```typescript theme={null}
interface Repo {
  id: number
  name: string
  repo: string
  description: string
  stars: number
}

// From examples/type-safety.ts
const { repo } = await ofetch<{ repo: Repo }>(
  'https://ungh.cc/repos/unjs/ofetch'
)

console.log(`The repo ${repo.name} has ${repo.stars} stars.`)
// TypeScript knows repo.name is string and repo.stars is number
```

## Array Responses

```typescript theme={null}
interface User {
  id: number
  name: string
}

const users = await ofetch<User[]>('https://api.example.com/users')

users.forEach(user => {
  console.log(user.name)  // ✅ Typed correctly
})
```

## Response Type with responseType Option

The second generic parameter allows you to specify the response format:

```typescript theme={null}
// JSON response (default)
const data = await ofetch<User, 'json'>('/api/user')

// Text response
const text = await ofetch<string, 'text'>('/api/data', {
  responseType: 'text'
})

// Blob response
const blob = await ofetch<Blob, 'blob'>('/api/image', {
  responseType: 'blob'
})

// ArrayBuffer response
const buffer = await ofetch<ArrayBuffer, 'arrayBuffer'>('/api/binary', {
  responseType: 'arrayBuffer'
})

// Stream response
const stream = await ofetch<ReadableStream<Uint8Array>, 'stream'>('/api/stream', {
  responseType: 'stream'
})
```

## Type-Safe API Client

Create a fully typed API client:

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

interface User {
  id: number
  name: string
  email: string
}

interface CreateUserRequest {
  name: string
  email: string
}

class UserAPI {
  private client = ofetch.create({
    baseURL: 'https://api.example.com'
  })

  async getUser(id: number): Promise<User> {
    return this.client<User>(`/users/${id}`)
  }

  async createUser(data: CreateUserRequest): Promise<User> {
    return this.client<User>('/users', {
      method: 'POST',
      body: data
    })
  }

  async listUsers(): Promise<User[]> {
    return this.client<User[]>('/users')
  }
}

const api = new UserAPI()
const user = await api.getUser(123)
console.log(user.name)  // Fully typed!
```

## Hooks with Type Safety

Hooks are also fully typed:

```typescript theme={null}
interface User {
  id: number
  name: string
}

await ofetch<User>('/api/user', {
  onResponse({ response }) {
    // response._data is typed as User
    console.log(response._data.name)
  }
})
```

## Error Handling with Types

```typescript theme={null}
import { FetchError } from 'ofetch'

interface ErrorResponse {
  message: string
  code: string
}

try {
  const user = await ofetch<User>('/api/user/123')
} catch (error) {
  if (error instanceof FetchError) {
    const errorData = error.data as ErrorResponse
    console.log(errorData.message)
  }
}
```

## Type Definitions

From `src/types.ts:5-16`:

```typescript theme={null}
export interface $Fetch {
  <T = any, R extends ResponseType = "json">(
    request: FetchRequest,
    options?: FetchOptions<R>
  ): Promise<MappedResponseType<R, T>>;
  
  raw<T = any, R extends ResponseType = "json">(
    request: FetchRequest,
    options?: FetchOptions<R>
  ): Promise<FetchResponse<MappedResponseType<R, T>>>;
  
  native: Fetch;
  create(defaults: FetchOptions, globalOptions?: CreateFetchOptions): $Fetch;
}
```

The `MappedResponseType` helper (from `src/types.ts:132-135`):

```typescript theme={null}
export type MappedResponseType<
  R extends ResponseType,
  JsonType = any,
> = R extends keyof ResponseMap ? ResponseMap[R] : JsonType
```

This means:

* `responseType: 'blob'` → returns `Blob`
* `responseType: 'text'` → returns `string`
* `responseType: 'arrayBuffer'` → returns `ArrayBuffer`
* `responseType: 'stream'` → returns `ReadableStream<Uint8Array>`
* `responseType: 'json'` (default) → returns your generic type `T`
