TypedFetch
Type-safe HTTP client that doesn't suck - Fetch for humans who have stuff to build
Zero dependencies. Full type safety. Just works.
📦 npm: @catalystlabs/typedfetch
🌐 Website: typedfetch.dev
📚 Docs: typedfetch.dev/docs
💻 Source: git.catalystlab.cc/caseycollier/TypeFetched
🚀 Quick Start
bun add @catalystlabs/typedfetch
npm install @catalystlabs/typedfetch
import { tf } from '@catalystlabs/typedfetch'
const { data, response } = await tf.get('https://api.github.com/users/github')
console.log(data.name)
import { createTypedFetch } from '@catalystlabs/typedfetch'
const client = createTypedFetch({
baseURL: 'https://api.example.com',
headers: {
'Authorization': 'Bearer token'
}
})
const { data, response } = await client.get('/users/123')
✨ Features
🔒 Type Safety
- TypeScript inference for response data
- No manual type casting needed
- Type-safe error handling
🛡️ Built-in Resilience
- Automatic retries with exponential backoff
- Circuit breaker for failing endpoints
- Request caching (memory + IndexedDB)
- HTTP cache header respect
🚀 Simple API
- Clean, chainable API
- Standard HTTP methods: get(), post(), put(), delete()
- Consistent response format
- Zero boilerplate
⚡ Performance
- <15KB gzipped bundle
- Zero runtime dependencies
- Efficient caching
- Request deduplication
📚 Documentation
Basic Usage
import { tf } from '@catalystlabs/typedfetch'
const { data, response } = await tf.get('https://api.example.com/users')
const { data, response } = await tf.post('https://api.example.com/users', {
body: {
name: 'John Doe',
email: 'john@example.com'
}
})
const { data, response } = await tf.put('https://api.example.com/users/123', {
body: {
name: 'Jane Doe'
}
})
const { data, response } = await tf.delete('https://api.example.com/users/123')
Configuration
import { createTypedFetch } from '@catalystlabs/typedfetch'
const client = createTypedFetch({
baseURL: 'https://api.example.com',
headers: {
'Authorization': 'Bearer token',
'Content-Type': 'application/json'
},
timeout: 30000,
retry: {
attempts: 3,
delay: 1000,
maxDelay: 10000,
backoff: 'exponential'
},
cache: {
enabled: true,
ttl: 300000,
storage: 'memory'
}
})
import { tf } from '@catalystlabs/typedfetch'
tf.configure({
baseURL: 'https://api.example.com',
headers: {
'Authorization': 'Bearer token'
}
})
Response Format
All methods return a consistent response format:
const { data, response } = await tf.get('/endpoint')
Error Handling
try {
const { data, response } = await tf.get('/users/123')
} catch (error) {
if (error.response) {
console.log(error.response.status)
console.log(error.data)
} else if (error.request) {
console.log('Network error:', error.message)
} else {
console.log('Error:', error.message)
}
}
Advanced Features
Circuit Breaker
Automatically stops making requests to failing endpoints:
const client = createTypedFetch({
circuitBreaker: {
enabled: true,
failureThreshold: 5,
resetTimeout: 60000
}
})
Request Caching
Intelligent caching with multiple storage options:
const client = createTypedFetch({
cache: {
enabled: true,
ttl: 300000,
storage: 'indexeddb',
respectCacheHeaders: true
}
})
const { data } = await tf.get('/endpoint', {
headers: {
'X-Custom-Header': 'value'
}
})
🎯 Why TypedFetch?
vs Axios
- ✅ Built on modern fetch API
- ✅ Smaller bundle size
- ✅ Better TypeScript support
- ✅ Built-in resilience features
vs Native Fetch
- ✅ Automatic JSON parsing
- ✅ Better error handling
- ✅ Built-in retries and caching
- ✅ Simpler API
📦 Bundle Size
- Core: <15KB gzipped
- Zero runtime dependencies
- Tree-shakeable
- Works without build step
🌐 Browser Support
- Modern browsers (ES2020+)
- Node.js 18+
- Deno
- Bun
🤝 Contributing
We welcome contributions! Please see our Contributing Guide for details.
📄 License
MIT License - see LICENSE for details.
TypedFetch: Because life's too short for complex HTTP clients. 🚀