tezvyn:

How would you model fetchItem's return type with generics and conditional types?

AI-drafted, machine-checkedSource: typescriptlang.orgadvanced
WHAT IT TESTS

linking a generic boolean flag to a conditional return type.

ANSWER OUTLINE

define base and extended Item, return T extends true ? ExtendedItem : BaseItem, and overload the plain boolean case.

WHAT THIS TESTS: This question evaluates your ability to use TypeScript's type system to model API behavior at compile time. The interviewer wants to see if you understand conditional types, generic type parameters, and the subtle difference between the boolean primitive type and boolean literal types like true and false. It also checks whether you know how to avoid collapsing a conditional type into an unwanted union when the generic is not a literal.

A GOOD ANSWER COVERS: A strong answer starts by defining two interfaces: a BaseItem that contains the common fields, and an ExtendedItem that is either an intersection of BaseItem and a history property, or an interface that extends BaseItem. Next, it introduces a conditional return type such as T extends true ? ExtendedItem : BaseItem inside the function signature. Then it explains that T should be constrained to boolean, but that when T is the primitive boolean rather than the literal true or false, both branches of the conditional are possible and the result becomes a union. To solve this, the candidate should mention adding function overloads for the true and false cases, or using a const type parameter in newer TypeScript versions, so that literal arguments produce exact types while variables still receive the union.

COMMON WRONG ANSWERS: A common mistake is returning Item | ExtendedItem unconditionally, which forces every caller to narrow the result manually and defeats the purpose of the generic flag. Another red flag is writing runtime logic inside the function body without expressing the relationship at the type level, since the question explicitly asks for a generic and conditional type solution. Some candidates also forget that boolean is a supertype of true and false, so they are surprised when fetchItem with a boolean variable returns a union instead of a single concrete type.

LIKELY FOLLOW-UPS: The interviewer might ask how you would handle three or more query parameters, which leads to a discussion of combining multiple conditional types or using mapped types and template literal types to build a query-specific return shape. They might also ask how to type the actual fetch call inside the function, or how to derive the query string type from the generic parameter. Another follow-up is whether you would use function overloads instead of conditional types, and when each approach is preferable.

ONE CONCRETE EXAMPLE: Here is a minimal implementation. First, define interface BaseItem { id: string; name: string; } and interface ExtendedItem extends BaseItem { history: string[]; }. Then define type FetchResult<T extends boolean> = T extends true ? ExtendedItem : BaseItem. For the function signature, write function fetchItem<T extends boolean>(id: string, includeHistory: T): FetchResult<T>. To handle the primitive boolean case cleanly, add overloads: function fetchItem(id: string, includeHistory: true): ExtendedItem; function fetchItem(id: string, includeHistory: false): BaseItem; function fetchItem(id: string, includeHistory: boolean): BaseItem | ExtendedItem { /* runtime fetch */ }. This gives exact types for literal calls and a safe union for dynamic booleans.

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.