Distributive conditional types in Typescript - Time & Space Complexity
We want to understand how the time it takes to evaluate distributive conditional types changes as the input type grows.
Specifically, how does TypeScript handle conditional checks on union types?
Analyze the time complexity of the following TypeScript distributive conditional type.
type FilterString = T extends string ? T : never;
// Example usage:
type Result = FilterString<'a' | 1 | 'b' | boolean>;
This type checks each member of a union and keeps only the string members.
Look for repeated checks or operations in the type evaluation.
- Primary operation: Conditional check on each union member.
- How many times: Once per member in the union type.
Each union member is checked separately, so the work grows as the number of members grows.
| Input Size (n) | Approx. Operations |
|---|---|
| 3 | 3 conditional checks |
| 10 | 10 conditional checks |
| 100 | 100 conditional checks |
Pattern observation: The number of checks grows directly with the number of union members.
Time Complexity: O(n)
This means the time to evaluate grows linearly with the number of union members.
[X] Wrong: "The conditional type runs once for the whole union at once."
[OK] Correct: TypeScript actually distributes the conditional over each union member separately, so it runs multiple times.
Understanding how TypeScript processes distributive conditional types helps you reason about type performance and complexity in real projects.
"What if we changed the conditional type to not distribute over unions? How would the time complexity change?"
Practice
T extends U ? X : Y when T is a union type?Solution
Step 1: Understand conditional types with unions
WhenTis a union, TypeScript distributes the condition over each member separately.Step 2: Apply distributive behavior
Each member ofTis checked againstUindividually, returningXorYper member.Final Answer:
Applies the condition separately to each member of the union type -> Option AQuick Check:
Distributive conditional types = separate checks per union member [OK]
- Thinking the condition applies once to the whole union
- Assuming it always returns true or false branch
- Confusing distributive with non-distributive conditional types
Solution
Step 1: Recall correct conditional type syntax
Conditional types useT extends U ? X : Ysyntax in TypeScript.Step 2: Match syntax with options
type Result<T> = T extends string ? number : boolean; matches the correct syntax; others use invalid or incorrect syntax.Final Answer:
type Result<T> = T extends string ? number : boolean; -> Option DQuick Check:
Conditional types useextends ? :syntax [OK]
extends ? : pattern in type definitions [OK]- Using if-else instead of conditional operator
- Missing the extends keyword
- Using arrow functions incorrectly in type definitions
type FilterString<T> = T extends string ? T : never;
type Result = FilterString<'a' | 1 | 'b' | true>;
What is the type of
Result?Solution
Step 1: Apply distributive conditional type to each union member
Each member is checked: 'a' extends string (true), 1 extends string (false), 'b' extends string (true), true extends string (false).Step 2: Collect true branch results
Only 'a' and 'b' remain; others become never and are removed from union.Final Answer:
'a' | 'b' -> Option CQuick Check:
FilterString filters strings only = 'a' | 'b' [OK]
- Thinking the whole union is returned unchanged
- Confusing never with empty string
- Assuming the result is just string instead of filtered literals
type ExtractNumber<T> = [T] extends [number] ? T : never;
type Result = ExtractNumber<'a' | 1 | 2>;
Solution
Step 1: Understand tuple wrapping effect
WrappingTin a tuple disables distributive behavior in conditional types.Step 2: Analyze impact on
Since distribution is off, the whole union is checked at once, soExtractNumber'a' | 1 | 2extendsnumberis false, returning never.Final Answer:
The condition is wrapped in a tuple, so distribution does not occur -> Option AQuick Check:
Tuple wrapping disables distributive conditional types [OK]
- Assuming distribution still happens with tuple wrapping
- Confusing syntax error with logic error
- Thinking union types are not allowed in conditional types
T into a union of their array types using distributive conditional types?Choose the correct type definition.
Solution
Step 1: Understand distributive conditional type for mapping
UsingT extends any ? T[] : neverapplies the array transformation to each union member separately.Step 2: Compare options
type ToArray<T> = T extends any ? T[] : never; correctly distributes and converts each member to an array type. type ToArray<T> = [T] extends [any] ? T[] : never; disables distribution by tuple wrapping. type ToArray<T> = T[]; wraps the whole union as an array, not each member. type ToArray<T> = T extends any[] ? T : never; filters arrays, not converts.Final Answer:
type ToArray<T> = T extends any ? T[] : never; -> Option BQuick Check:
Distributive conditional types map unions member-wise [OK]
T extends any ? to distribute over unions [OK]- Wrapping
Tin tuple disables distribution - Using
T[]directly converts whole union, not members - Confusing filtering with mapping in conditional types
Ready to prove it?
Pass the test and this pattern moves unknown
