Write a generic fetchJSON<T> wrapper and explain its type safety benefits
Tests preserving type info across async boundaries via generics. Outline: write fetchJSON<T> returning Promise<T>, note response.json() is any, and show T lets callers lock in the response shape for compile-time checks.
WHAT THIS TESTS: This question evaluates whether you understand that TypeScript generics are not just syntax sugar but a mechanism for trafficking type information through a function boundary. Specifically, it checks if you know that response.json() erases type information by returning Promise<any>, and whether you can use a generic parameter T to reintroduce that information at the call site without hardcoding a specific interface inside the wrapper.
A GOOD ANSWER COVERS: First, the signature: fetchJSON<T> takes a URL string and returns Promise<T>. Second, the implementation fetches the URL, checks response.ok, then returns response.json() as Promise<T>. Third, the candidate must explain that without T the wrapper would return Promise<any>, forcing every consumer to use type assertions or accept the loss of autocomplete and compile-time checking. Fourth, the candidate should clarify that T is supplied by the caller, so each invocation can specify a different expected shape, making the wrapper reusable across endpoints. Fifth, a strong answer notes that generics do not perform runtime validation; they only tell the compiler what the developer expects.
COMMON WRONG ANSWERS: A red flag is writing the wrapper without the generic parameter and returning Promise<any>, which defeats the purpose of type safety. Another mistake is using a type assertion like response.json() as T inside the wrapper, because this still relies on any and merely hides the problem. Some candidates claim that T validates the JSON payload at runtime, which is false; TypeScript generics are erased during compilation. Finally, forgetting to handle HTTP errors by checking response.ok before parsing is a practical gap that interviewers notice even though it is not strictly about generics.
LIKELY FOLLOW-UPS: The interviewer may ask how you would add runtime validation, perhaps by combining the generic wrapper with a schema library like Zod so that the returned value is both statically typed and runtime-checked. They might also ask how to type request headers or a POST body, extending the generic to cover the full request lifecycle. Another follow-up is handling non-JSON responses or adding a timeout, which tests how the type contract changes when the function can fail in multiple ways.
ONE CONCRETE EXAMPLE: Imagine an endpoint that returns a user profile with id and name fields. With a non-generic wrapper, the consumer writes const data = await fetchJSON("/user/1") and data is any, so data.nmae compiles silently. With fetchJSON<User>, the call becomes const data = await fetchJSON<User>("/user/1"), and the compiler immediately flags data.nmae as an error because User does not contain that property. The generic T traffics the User type into the Promise, preserving autocomplete and catching typos before the code runs.
Read the original → typescriptlang.org
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.