Skip to content
tezvyn:

Write a typed async fetchUser with error handling

Source: developer.mozilla.orgMediumHow cards are made

Write a typed async fetchUser with error handling

Tests promise-based fetch plus TypeScript return-type contracts. A strong answer checks response.ok before response.json() and types the return as Promise<User>. A red flag is swallowing 4xx/5xx errors silently.

What's really being asked

This question probes three distinct skills that separate mid-level from senior TypeScript engineers. First, it checks whether you know the fetch API resolution semantics: fetch promises resolve on HTTP error status codes like 404 or 500, and only reject on network failures. Second, it tests whether you can correctly type an async function return value as Promise<User> rather than just User. Third, it reveals whether you treat TypeScript types as runtime guarantees or compile-time hints, since JSON parsing returns any and you must explicitly handle error states.

The full answer

A strong implementation hits four points in order. First, construct the URL with template literals and call fetch with it. Second, check response.ok and throw a descriptive Error if it is false, because fetch does not auto-reject on 4xx or 5xx status codes. Third, call await response.json() and return the result, relying on the Promise<User> return type annotation for downstream type safety. Fourth, optionally note that json() itself returns a promise and must be awaited, and that the function signature should explicitly declare Promise<User> so callers know it is async.

The mistakes people make

The most frequent red flag is skipping the ok check and assuming fetch throws on non-200 responses. Another mistake is writing return response.json() without await, which technically returns Promise<Promise<User>> and can confuse callers. Some candidates omit the Promise<User> return type entirely, weakening the contract. A subtler error is claiming the returned JSON is guaranteed to match the User interface at runtime; TypeScript does not validate shapes during JSON parsing, so a runtime check or schema validation is needed for true safety.

What usually comes next

Interviewers often ask how you would validate the JSON shape at runtime, leading to discussions about Zod, io-ts, or manual guards. They may also ask how to abort an in-flight request, prompting the AbortController pattern. Another common extension is handling transient 5xx errors with exponential backoff, or asking how you would type a generic fetch wrapper that accepts any response interface.

A concrete example

Here is a minimal correct implementation. async function fetchUser(id: number): Promise<User> { const response = await fetch("/api/users/" + id); if (!response.ok) { throw new Error("HTTP error: " + response.status); } return await response.json(); } This satisfies all requirements: it is async, it types the return as Promise<User>, it checks response.ok before parsing, and it throws on unsuccessful HTTP status codes.

Interview question

In an async TypeScript function fetchUser(id: number): Promise<User> that wraps fetch, what is the primary reason to check response.ok before calling response.json()?

  • a.TypeScript uses the ok check to narrow the response type to User before json() is called.
  • b.fetch rejects on HTTP error statuses, and ok prevents an unhandled rejection during parsing.
  • c.fetch resolves even on 4xx or 5xx statuses, so ok is needed to detect HTTP failures before parsing.Correct
  • d.response.json() throws if the HTTP status is not 2xx, so ok is required to avoid a parse exception.
Why?

fetch resolves rather than rejects on HTTP error codes such as 404 or 500, so checking response.ok is the only way to detect server-side failures before parsing. Distractor A repeats the common misconception that fetch auto-rejects on 4xx/5xx, which would make the ok check unnecessary.

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