Safe Requests: Go/Rust-Style Tuples
Eliminate nested try / catch boilerplate across your codebase with the dedicated api.safe.* namespace.
The Problem with Traditional try / catch
In JavaScript and TypeScript, catch (e: unknown) loses type safety. Variables declared inside the try block are scoped locally, forcing developers to declare loose let data: MyType | undefined outside the block.
The api.safe namespace returns a Promise<SafeResult<T>>—a strongly typed tuple representing either [data, null] or [null, FetchNativeError].
Safe GET Requests
safe-get.ts
typescript
import { createClient } from 'react-native-fetch-client';
const api = createClient({ baseURL: 'https://api.example.com' });
interface Product {
id: string;
name: string;
price: number;
}
// Returns [data, null] on success, or [null, error] on failure
const [product, error] = await api.safe.get<Product>('/products/123');
if (error) {
// TypeScript narrows error to FetchNativeError
console.error('Could not load product:', error.message);
showErrorToast(error.message);
return;
}
// TypeScript narrows product to Product (non-null!)
console.log('Product loaded:', product.name, product.price);Safe Mutations (POST, PUT, PATCH, DELETE)
All HTTP verbs are available on the api.safe object:
typescript
// Safe POST mutation
const [created, postErr] = await api.safe.post('/products', {
name: 'Mechanical Keyboard',
price: 99.99,
});
if (postErr) {
alert('Creation failed: ' + postErr.message);
return;
}
// Safe DELETE mutation
const [deleted, delErr] = await api.safe.delete('/products/123');TypeScript Discriminated Union
Because the tuple is typed as
[T, null] | [null, FetchNativeError], checking if (error) return; automatically narrows data from T | null to T with 100% type soundness!