Today, I dove deeper into TypeScript and explored how to safely fetch and use data from an API. Now I understand how TypeScript helps prevent bugs, improve developer experience, and makes code more maintainable.
Understanding the Problem
When we fetch data from an API in JavaScript, we usually do something like:
const response = await fetch("https://randomuser.me/api/?results=3");
const data = await response.json();
console.log(data);
JavaScript doesn't care about types. The code will run even if the API changes its structure or fields. But in TypeScript:
response.json() returns any (or unknown depending on settings)
TypeScript doesn't know the shape of the data, so we can't safely access nested properties without risking errors. This is where type assertions come in.
The images above illustrate the JSON structure returned by the RandomUser API and the EscuelaJS Products API respectively, which I used to practice TypeScript type assertions and API data typing. As you can see the structure of the data they return differs.
Using TypeScript Type Assertions
Type assertions tell TypeScript: "I know the structure of this data better than you do."
Example:
`const data = await response.json();
const users = data as unknown as {
results: {
name: { first: string; last: string };
email: string;
picture: { large: string };
}[];
};`
data is unkown after response.json()
as unknown as {…} tells TS: "Treat data as an object with a results array containing this exact structure"
This allows us to safely access nested properties like results[0].name.firstwithout TypeScript complaining.
The double assertion (as unknown as) is sometimes needed when TypeScript is too conservative and refuses a direct conversion.
Mapping API Data to Your Own Types
Even after asserting the type, I didn't want to expose the entire nested API structure in my app. So I mapped the data to my own simpler type:
`export type User = {
name: string;
email: string;
picture: string;
};
return users.results.map(u => ({
name: ${u.name.first} ${u.name.last},
email: u.email,
picture: u.picture.large
}));`
Now, the rest of my app can safely work with a clean, predictable User[] array, with proper typing and autocomplete support.
Why This Matters
Through this exercise, I realized how TypeScript helps in several ways:
Prevent runtime crashes: TS catches mistakes before the code runs
Autocompletion / IntelliSense: helps write code faster with fewer typos
Self-documenting code: types tell anyone reading the code exactly what data looks like
Safe refactoring: if I rename a field or the API changes, TS will warn me
Even small experiments like fetching users or products can teach you how typed async flows work in real projects.
Key points
TypeScript doesn't magically know API data, so we teach it using types or type assertions
Mapping API data to our own types makes apps safer and easier to work with




Top comments (0)