tezvyn:

Implement MyReturnType<T> using conditional types and infer

AI-drafted, machine-checkedSource: typescriptlang.orgadvanced

This tests type-level pattern matching with conditional types and infer. Answer uses T extends (...args: any[]) => infer R ? R : never, noting infer captures return slot, non-functions yield never. Red flag: conflating runtime values with compile-time types.

WHAT THIS TESTS: This question probes your understanding of TypeScript's type system as a logic language rather than a value system. Specifically, it checks if you know how to use conditional types for pattern matching and how infer creates type variables during that matching. The interviewer wants to see that you grasp structural typing at the type level and can decompose function signatures without executing code. They also care whether you understand that this computation happens entirely at compile time and erases to nothing in the emitted JavaScript.

A GOOD ANSWER COVERS: First, write the exact shape: type MyReturnType<T> = T extends (...args: any[]) => infer R ? R : never. Second, explain that T extends (...args: any[]) => infer R pattern-matches T against any function type regardless of parameter count or names. Third, describe infer R as introducing a type variable that captures whatever appears in the return type slot of the matched function. Fourth, note that the never branch is the false case for when T is not a function, which preserves type safety by making invalid usage unassignable. Fifth, mention that any[] for arguments is idiomatic because we only care about the output shape, not input constraints. Finally, emphasize that the type system evaluates this instantly and produces a concrete type for downstream use.

COMMON WRONG ANSWERS: A major red flag is writing runtime logic like return typeof fn or trying to call T() inside the type declaration. Another mistake is forgetting the never fallback and leaving the false branch as T or unknown, which silently allows non-functions to pass through. Some candidates use unknown[] instead of any[] for the arguments and then cannot explain why stricter parameter typing might break inference on functions with rest parameters or tuple types. Confusion between generic value parameters and generic type parameters also signals a shallow understanding. A subtle error is writing infer without a conditional extends wrapper, which produces a syntax error because infer is only valid in the extends clause of a conditional type.

LIKELY FOLLOW-UPS: The interviewer may ask how to extract parameter types instead, which swaps infer R into the argument position. They might ask what happens with overloaded functions, where inference resolves to the last overload's return type. They could also ask you to constrain T to extend Function, which changes the conditional to a constrained generic rather than a fallback to never. Another variant is implementing a version that returns void instead of never for non-functions. You might also be asked to handle async functions or to build a version that unwraps Promise<infer R> recursively.

ONE CONCRETE EXAMPLE: Given type Fn = () => { id: number }, MyReturnType<Fn> evaluates to { id: number }. If you pass string, you get never, preventing accidental assignment. If you pass a generic function like <T>(x: T) => T[], MyReturnType captures T[] in the infer R position, showing that infer works with generic signatures too. For a union of functions, the conditional type distributes over the union and gives back a union of return types, which is often the behavior callers actually want.

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.