Skip to content
tezvyn:

Typing `fetch` Responses in TypeScript

Source: developer.mozilla.orgMediumHow cards are made

Typing `fetch` Responses in TypeScript

The fetch promise resolves to a generic Response, not your typed data. You must first parse the body with .json(), then assert the type of the resulting data. This is essential for all API calls.

Why it exists

The fetch API operates at the HTTP level, returning a generic wrapper for the entire response. It knows nothing about the JSON payload inside. TypeScript, a static type system, needs your help to bridge the gap between the untyped world of network I/O and the typed world of your application code.

The mental model

Think of fetch as a mail carrier delivering a sealed envelope (the Response object). The carrier doesn't know what the letter inside says. You must first receive the envelope, check that it's not damaged (response.ok), and only then open it (response.json()) and apply your own understanding of its contents (the type assertion).

How it works

Using fetch in TypeScript is a two-step promise chain. First, fetch(url) returns a Promise<Response>. The Response object is not your data. Second, you call a method like response.json() to parse the response body. This method returns a Promise<any> because TypeScript can't know the shape of the incoming JSON. Your job is to provide the type for the resolved value of this second promise, typically with an as assertion: const data = await response.json() as MyType;. For more safety, you can use a validation library like Zod to parse and validate the data instead of just asserting its type.

When to use it

Always follow this pattern when fetching JSON data with the native fetch API in TypeScript. The process is: fetch, check the response status, parse the body, and then apply your type to the parsed data. This ensures type safety for data coming from external sources.

When not to use it

Do not try to add a generic type to the fetch call itself, like fetch<User>('/api/users/1'). The standard fetch signature is not generic this way, so this has no effect and is a common mistake. The type information belongs on the result of response.json(), not the initial call. Data-fetching libraries like Axios or TanStack Query often abstract this pattern away, but they perform the same steps internally.

One canonical example

To fetch a user object, you'd define interface User { id: number; name: string; }. In an async function, you get the response: const response = await fetch('/api/users/1');. Then, you must check if the request was successful: if (!response.ok) { throw new Error('Network response was not ok'); }. Finally, you parse the body and tell TypeScript its shape: const user = await response.json() as User;. Now you can safely access user.name.

Interview question

When using the native fetch API in TypeScript, how do you correctly apply type safety to the JSON data received from an API?

  • a.By relying on response.json() to return a Promise<MyType> without further type annotations.
  • b.By adding a generic type argument directly to the fetch call, such as fetch<MyType>(url).
  • c.By performing a type assertion on the result of await response.json().Correct
  • d.By accessing properties directly from the Response object, as it automatically infers the JSON structure.
Why?

The card explains that `response.json()` returns `Promise<any>`, so you must explicitly assert the type of the parsed data using `as MyType`. Adding a generic type to the `fetch` call itself is a common mistake and has no effect, and the `Response` object does not automatically infer the JSON payload's type.

Just read this? Test yourself on what you have been reading.

Read the original → developer.mozilla.org

You just looked this up. Could you explain it out loud?

That is the part interviews actually test. Tezvyn takes questions like this one and gives you what the interviewer is really checking, the answer that lands, and the mistake that ends the conversation, in the four minutes before your next meeting.

The iPhone app is on the way

We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.

Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.

Get it on Google PlayiPhone app coming soon

We are hiring for this. Open roles that interview on typescript — each one lists the topics its interview covers.

See open roles