Type Challenges (Tips)
TL;DR
If you are faced with a complex “Type Challenge” in an interview, remember the three fundamental tools of type-level programming: Conditional Types (for if/else), Mapped Types (for loops/iteration), and infer (for pattern matching and extracting).
1. The “If/Else” Tool: Conditional Types
Whenever a challenge asks you to filter, check, or branch logic based on a type, use T extends Condition ? True : False.
Challenge: Write an Exclude<T, U> type.
Thought Process: “I need to loop over a union T, check if it matches U, and if so, discard it.”
Solution: T extends U ? never : T (Conditionals over unions automatically distribute!)
2. The “Loop” Tool: Mapped Types
Whenever a challenge asks you to transform the properties of an object, use [K in keyof T].
Challenge: Write an OptionalProperties<T> type.
Thought Process: “I need to iterate over every key in T, and append a ? modifier.”
Solution: { [K in keyof T]?: T[K] }
3. The “Pattern Matching” Tool: infer
Whenever a challenge asks you to extract a specific piece of data buried deep inside a string, an array, a promise, or a function, use infer.
Challenge: Write an UnwrapPromise<T> type.
Thought Process: “I need to check if T is a Promise, and if it is, I need to extract whatever is inside the < >.”
Solution: T extends Promise<infer U> ? U : T
4. The “Recursion” Tool
Whenever a challenge involves arrays of unknown length or strings, you often need recursion combined with infer.
Challenge: Write a TupleLength<T> type. (Assuming T is an array).
Thought Process: “I can just access the length property of the tuple.”
Solution: T extends readonly any[] ? T['length'] : never
Challenge: Write a ReverseTuple<T> type.
Thought Process: “I need to extract the first element, and put it at the end, and repeat.”
Solution: T extends [infer First, ...infer Rest] ? [...ReverseTuple<Rest>, First] : []
Summary Checklist for Interviews
- Is it an Object? -> Use Mapped Types
{ [K in keyof T]: ... }. - Is it a Union? -> Use Conditional Types
T extends U ? ...(Distributive property). - Do I need a piece of it? -> Use
inferinside a Conditional Type. - Is it deeply nested? -> Call the type from within itself (Recursion).