Better Fetch

Handling Errors

Default Error Type

Better fetch by default returns response errors as a value. By defaullt, the error object has 3 properties status, statusText and message properties.

status and statusText are always defined. If the api returns a json error object it will be parsed and returned with the error object. By default error includes message property that can be string or undefined.

fetch.ts
import {  } from '@better-fetch/fetch';
import {  } from 'zod';
 
const {  } = await ("https://jsonplaceholder.typicode.com/todos/1");
 
Hover over the error object to see the type

Custom Error Type

You can pass a custom error type to be inferred as a second generic argument.

import { betterFetch } from 'better-fetch';
 
const { error } = await betterFetch<{
    id: number;
    userId: string;
    title: string;
    completed: boolean;
}, 
{ 
    message?: string; 
    error?: string;
}>("https://jsonplaceholder.typicode.com/todos/1");

If you pass a custom error type, it will override the default error type except for the status and statusText properties. If you still need the message property, you need to include it in your custom error type.

Throwing Errors

If you prefer to throw errors instead of returning them, you can use the throw option.

When you pass the throw option, the betterFetch function will throw an error. And instead of returning data and error object it'll only the response data as it is.

fetch.ts
import {  } from '@better-fetch/fetch';
import {  } from 'zod';
 
const  = await ("https://jsonplaceholder.typicode.com/todos/1", {
    : true, 
    : .({  
        : .(),
        : .(),
        : .(),
        : .(),
    }),
});

Inferring Response When Using Generics and throw Option

When you pass the throw option to the betterFetch function, it will throw an error instead of returning it. This means the error will not be returned as a value. However, if you specify the response type as a generic, the error object will still be returned, and data will be inferred as possibly null or the specified type. This issue arises because the throw option cannot be inferred when a generic value is passed, due to a TypeScript limitation.

To address this, you have two options. If you use either option, the error object will no longer exist, and the response type will be inferred correctly without being unioned with null.

  1. Create a custom fetch instance with the throw option.
fetch.ts
import {  } from "@better-fetch/fetch";
 
export const  = ({
  : "https://jsonplaceholder.typicode.com",
  : 2,
  : true,
}); 
 
 
const  = await <{
  : number;
  : number;
  : string;
  : boolean;
}>("/todos/1");
  1. Pass false as a second generic argument to the betterFetch function.
fetch.ts
import {  } from '@better-fetch/fetch';
import {  } from 'zod';
 
const  = await <{
    : number;
    : number;
    : string;
    : boolean;
}, 
false
>("https://jsonplaceholder.typicode.com/todos/1");

On this page