What Is a Conditional Type in TypeScript?
Understand TypeScript conditional types: the extends ? : syntax, distributive behavior over unions, the infer keyword, and real code examples.
Expected Interview Answer
A conditional type is a type-level expression written as 'T extends U ? X : Y' that picks between two resulting types based on whether one type is assignable to another, letting TypeScript compute new types from existing ones the way an if-statement computes values.
Conditional types become distributive when the checked type is a naked generic union, meaning the condition is applied to each union member separately and the results are combined back into a union. This distribution is what lets utilities like Exclude and Extract filter union members individually. Conditional types also support the infer keyword, which captures a type from within the true branch of the check, enabling utilities like ReturnType and Parameters to pull a function's return type or argument tuple out of its signature without knowing it in advance. Together, distribution and infer make conditional types the mechanism behind most of TypeScript's built-in utility types.
- Computes new types from existing ones based on a condition
- Distributes automatically over naked union type parameters
- Uses infer to extract nested types like return values
- Powers built-in utilities such as Exclude, Extract, and ReturnType
- Enables reusable, generic type-level logic instead of duplication
AI Mentor Explanation
A conditional type is like a standing team rule that says if the opposition's opener is left-handed, the captain brings on a particular bowler, otherwise a different one — the choice is computed fresh for each new batter rather than fixed in advance. When the rule is applied across an entire top order, it distributes down the batting list, producing a matched bowler for every single name.
Step-by-Step Explanation
Step 1
Basic syntax
'T extends U ? X : Y' resolves to X if T is assignable to U, and to Y otherwise, evaluated at the type level.
Step 2
Distributive behavior
When T is a naked generic type parameter bound to a union, the condition applies to each union member separately and the results union back together.
Step 3
The infer keyword
Inside the extends clause, 'infer R' introduces a new type variable that captures a matched piece of the structure for use in the true branch.
Step 4
Built-in utility examples
Exclude<T, U> = T extends U ? never : T removes matching union members; ReturnType<T> uses infer to pull out a function's return type.
Step 5
Non-distributive form
Wrapping T in a tuple like [T] extends [U] disables distribution when you need to compare the whole union at once.
What Interviewer Expects
- Can write the basic 'T extends U ? X : Y' syntax from memory
- Explains distributive behavior over naked union generics
- Understands how infer captures a type inside the true branch
- Can trace how Exclude or ReturnType are implemented internally
- Knows how to disable distribution using a tuple wrapper
Common Mistakes
- Not realizing conditional types distribute automatically over unions
- Misusing infer outside the extends clause where it is not allowed
- Assuming conditional types run at runtime rather than purely at compile time
- Forgetting the tuple-wrapping trick to disable unwanted distribution
Best Answer (HR Friendly)
“A conditional type lets a codebase describe a rule like 'if this data looks like one shape, treat it as type A, otherwise treat it as type B,' and the compiler works that out automatically instead of a developer writing it by hand for every case. This is what powers many built-in TypeScript helpers, saving teams from repeating the same type logic across a project.”
Code Example
// Distributive: applies to each union member separately
type NonNullableCustom<T> = T extends null | undefined ? never : T;
type A = NonNullableCustom<string | null>; // string
// infer captures the return type of a function signature
type MyReturnType<T> = T extends (...args: any[]) => infer R ? R : never;
type B = MyReturnType<() => number>; // number
// Disabling distribution with a tuple wrapper
type IsUnion<T, U = T> = T extends U
? [U] extends [T] ? false : true
: never;Follow-up Questions
- What does it mean for a conditional type to be distributive?
- How does the infer keyword work inside a conditional type?
- How is Exclude implemented using a conditional type?
- How do you prevent a conditional type from distributing over a union?
- How does ReturnType extract a function's return type?
MCQ Practice
1. What does 'T extends U ? X : Y' represent?
This is the conditional type syntax, resolving to X or Y at the type level depending on whether T is assignable to U.
2. When does a conditional type distribute over a union?
Distribution happens specifically when a naked generic type parameter is instantiated with a union type.
3. What does the infer keyword do inside a conditional type?
infer introduces a new type variable inside the extends clause that captures part of the matched type.
Flash Cards
What is the basic syntax of a conditional type? — T extends U ? X : Y — resolves to X if T is assignable to U, otherwise Y.
When does a conditional type distribute? — When the checked type is a naked generic type parameter instantiated with a union.
What does infer do? — Captures a type from within the matched structure inside the extends clause, usable in the true branch.
How do you disable distribution? — Wrap both sides in tuples, e.g. [T] extends [U], so the union is compared as a whole.