# Chapter 2: Enter TypedFetch - Your API Superpower *"The difference between a tool and a superpower is how it makes you feel when you use it."* --- ## The Moment Everything Changes Remember Sarah from Chapter 1? She'd figured out APIs, but her code was getting messy. Error handling was a nightmare. Every API call looked like this: ```javascript fetch('https://api.weather.com/forecast') .then(response => { if (!response.ok) { if (response.status === 404) { throw new Error('City not found') } else if (response.status === 401) { throw new Error('Invalid API key') } else { throw new Error('Something went wrong') } } return response.json() }) .then(data => { // Finally! The actual data updateWeatherDisplay(data) }) .catch(error => { console.error('Error:', error) showErrorMessage(error.message) }) ``` 15 lines of code just to make one API call. And she had dozens of these throughout her app. Then her colleague Dave walked by. "Why are you writing all that boilerplate? Just use TypedFetch." "TypedFetch?" Dave smiled and rewrote her code: ```javascript import { tf } from 'typedfetch' const { data } = await tf.get('https://api.weather.com/forecast') updateWeatherDisplay(data) ``` Sarah stared. "That's it?" "That's it." ## Installing Your Superpower Let's get TypedFetch into your project. It takes literally one command: ```bash npm install typedfetch ``` Or if you prefer yarn/pnpm/bun: ```bash yarn add typedfetch pnpm add typedfetch bun add typedfetch ``` That's it. No configuration files. No setup wizard. No initialization. It just works. ## Your First TypedFetch Call Let's rewrite that dad joke fetcher from Chapter 1: ```javascript // The old way (fetch) fetch('https://icanhazdadjoke.com/', { headers: { 'Accept': 'application/json' } }) .then(response => response.json()) .then(data => console.log(data.joke)) .catch(error => console.error('Error:', error)) // The TypedFetch way import { tf } from 'typedfetch' const { data } = await tf.get('https://icanhazdadjoke.com/', { headers: { 'Accept': 'application/json' } }) console.log(data.joke) ``` Notice what's missing? All the ceremony. The `.then()` chains. The manual JSON parsing. The basic error handling. TypedFetch handles all of that for you. ## But Wait, What About Errors? Great question! Let's break something on purpose: ```javascript try { // This URL doesn't exist const { data } = await tf.get('https://fakesiteabcd123.com/api') } catch (error) { console.log(error.message) console.log(error.suggestions) // <- This is new! } ``` Output: ``` Failed to fetch https://fakesiteabcd123.com/api: fetch failed Suggestions: • Check network connection • Verify URL is correct • Try again in a moment ``` TypedFetch doesn't just tell you something went wrong - it helps you fix it. Every error comes with: - A clear error message - Suggestions for fixing it - Debug information when you need it ## The Magic of Zero Configuration Here's what TypedFetch configures automatically: 1. **JSON Parsing** - Response automatically parsed 2. **Error Handling** - Network and HTTP errors caught 3. **Content Headers** - Sets 'Content-Type' for you 4. **Smart Retries** - Retries failed requests intelligently 5. **Request Deduplication** - Prevents duplicate simultaneous calls Let's see this in action: ```javascript // Making multiple simultaneous calls to the same endpoint const promise1 = tf.get('https://api.github.com/users/torvalds') const promise2 = tf.get('https://api.github.com/users/torvalds') const promise3 = tf.get('https://api.github.com/users/torvalds') const [result1, result2, result3] = await Promise.all([promise1, promise2, promise3]) // TypedFetch only made ONE actual network request! // All three promises got the same result ``` ## Let's Upgrade Weather Buddy Remember our weather app from Chapter 1? Let's give it the TypedFetch treatment: ```html Weather Buddy 2.0

Weather Buddy 2.0 🌤️

``` Look at that error handling! If something goes wrong, TypedFetch tells the user exactly what happened and how to fix it. ## The TypedFetch Philosophy TypedFetch follows three core principles: ### 1. **Batteries Included** 🔋 Everything you need is built-in. No plugins to install, no middleware to configure. ```javascript // Caching? Built-in. const user1 = await tf.get('/api/user/123') // Network call const user2 = await tf.get('/api/user/123') // Cache hit! // Retries? Built-in. const data = await tf.get('/flaky-api') // Automatically retries on failure // Type safety? Built-in. (We'll cover this in Chapter 7) const user = await tf.get('/api/user/123') ``` ### 2. **Progressive Disclosure** 📈 Simple things are simple. Complex things are possible. ```javascript // Simple: Just get data const { data } = await tf.get('/api/users') // Advanced: Full control when you need it const { data, response } = await tf.get('/api/users', { headers: { 'Authorization': 'Bearer token' }, cache: false, retries: 5, timeout: 10000 }) console.log('Status:', response.status) console.log('Headers:', response.headers) ``` ### 3. **Developer Empathy** ❤️ Every feature is designed to make your life easier. ```javascript // Debugging? One line. tf.enableDebug() // Now every request logs helpful information: // [TypedFetch] GET https://api.example.com/users // [TypedFetch] ✅ 200 OK (123ms) // [TypedFetch] 📦 Response size: 2.4kb // [TypedFetch] 💾 Cached for 5 minutes ``` ## Real-World Comparison Let's fetch a GitHub user with both approaches: ### The fetch() Way: ```javascript async function getGitHubUser(username) { try { const response = await fetch(`https://api.github.com/users/${username}`) if (!response.ok) { if (response.status === 404) { throw new Error(`User ${username} not found`) } else if (response.status === 403) { throw new Error('Rate limit exceeded. Try again later.') } else { throw new Error(`HTTP ${response.status}: ${response.statusText}`) } } const data = await response.json() return data } catch (error) { if (error instanceof TypeError) { throw new Error('Network error. Check your connection.') } throw error } } ``` ### The TypedFetch Way: ```javascript async function getGitHubUser(username) { const { data } = await tf.get(`https://api.github.com/users/${username}`) return data } ``` Both handle errors properly. Both work with async/await. But which one would you rather write 50 times in your app? ## Common Questions (With Answers!) **Q: "Is TypedFetch just a wrapper around fetch()?"** A: It's like asking if a Tesla is just a wrapper around wheels. Yes, it uses fetch() internally, but adds intelligent caching, automatic retries, error enhancement, type safety, request deduplication, and more. **Q: "What about bundle size?"** A: The entire core is ~12KB gzipped. For context, that's smaller than most images on a webpage. **Q: "Does it work in Node.js/Deno/Bun?"** A: Yes! TypedFetch works everywhere fetch() works. **Q: "What if I need the raw Response object?"** A: You got it: ```javascript const { data, response } = await tf.get('/api') console.log(response.headers.get('content-type')) ``` **Q: "Can I still use async/await?"** A: That's the ONLY way to use TypedFetch. No more callback hell or promise chains. ## Your New Superpowers Here's what you can now do that you couldn't before: ```javascript // 1. Automatic caching const user = await tf.get('/api/user') // First call: ~200ms const cached = await tf.get('/api/user') // Second call: ~1ms // 2. Smart errors try { await tf.get('/bad-endpoint') } catch (error) { console.log(error.suggestions) // Actually helpful! } // 3. Request deduplication // If you accidentally call the same endpoint multiple times const [a, b, c] = await Promise.all([ tf.get('/api/data'), tf.get('/api/data'), tf.get('/api/data') ]) // Only ONE network request is made! // 4. Built-in debugging tf.enableDebug() // See everything that's happening // 5. Zero config // No setup, no initialization, just import and use ``` ## Practice Time! 🏋️ ### Exercise 1: Convert to TypedFetch Take these fetch() calls and rewrite them using TypedFetch: ```javascript // 1. Basic GET fetch('https://api.quotable.io/random') .then(r => r.json()) .then(data => console.log(data)) // 2. POST with data fetch('https://jsonplaceholder.typicode.com/posts', { method: 'POST', body: JSON.stringify({ title: 'My Post', body: 'This is the content', userId: 1 }), headers: { 'Content-Type': 'application/json' } }) .then(r => r.json()) .then(data => console.log(data)) ``` ### Exercise 2: Error Enhancement Make this request fail and examine the error: ```javascript try { // This domain doesn't exist await tf.get('https://this-domain-definitely-does-not-exist-123456.com/api') } catch (error) { console.log('Message:', error.message) console.log('Type:', error.type) console.log('Suggestions:', error.suggestions) // Try the debug function if (error.debug) { error.debug() } } ``` ### Exercise 3: Cache Detective Prove that TypedFetch is caching: ```javascript // Time the first call console.time('First call') await tf.get('https://api.github.com/users/torvalds') console.timeEnd('First call') // Time the second call console.time('Second call') await tf.get('https://api.github.com/users/torvalds') console.timeEnd('Second call') // What's the difference? ``` ## Key Takeaways 🎯 1. **TypedFetch is a zero-config API client** - Just install and use 2. **It handles all the boilerplate** - JSON parsing, error handling, headers 3. **Errors are actually helpful** - With suggestions and debug info 4. **Smart features work automatically** - Caching, retries, deduplication 5. **Progressive disclosure** - Simple by default, powerful when needed ## What's Next? You've got TypedFetch installed and you've seen its power. But we've only scratched the surface. In Chapter 3, we'll dive deep into GET requests and discover features like: - Query parameter magic - Response transformations - Custom headers and authentication - Performance optimization - Real-time data fetching We'll also evolve Weather Buddy to show live updates, handle multiple cities, and add a search feature - all powered by TypedFetch's GET superpowers. Ready to master the art of reading data from APIs? See you in Chapter 3! 🚀 --- ## Chapter Summary - TypedFetch is a zero-configuration API client that makes fetch() calls simple - Installation is one command: `npm install typedfetch` - Basic usage: `const { data } = await tf.get(url)` - Automatic features: JSON parsing, error handling, caching, retries, deduplication - Errors include helpful messages and suggestions - Works everywhere: browsers, Node.js, Deno, Bun - Progressive disclosure: simple things are simple, complex things are possible - Weather Buddy upgraded with better error handling and cleaner code **Next Chapter Preview**: Deep dive into GET requests - the foundation of API communication. Learn query parameters, headers, authentication, and real-time updates.