What if you could tell TypeScript to treat a group of types as one, avoiding confusing splits and mistakes?
Why Non-distributive conditional types in Typescript? - Purpose & Use Cases
Imagine you have a list of different fruits and you want to check if each fruit is an apple or not. Doing this by hand means checking each fruit one by one and writing separate code for each case.
Manually checking each item is slow and easy to mess up. If the list grows or changes, you have to rewrite or copy-paste code many times, which leads to mistakes and wasted time.
Non-distributive conditional types let you write one smart rule that applies to the whole list at once, without splitting it up. This saves time and keeps your code clean and easy to change.
type Check<T> = T extends 'apple' ? 'Yes' : 'No'; type Result = Check<'apple' | 'banana'>; // 'Yes' | 'No' (distributes)
type Check<T> = [T] extends ['apple'] ? 'Yes' : 'No'; type Result = Check<'apple' | 'banana'>; // 'No' (no distribution)
This concept lets you control how TypeScript checks types, making your code smarter and more precise when working with groups of types.
When building a form that accepts different input types, you can use non-distributive conditional types to apply validation rules to the entire input type at once, instead of handling each input type separately.
Manual checks for each type are slow and error-prone.
Non-distributive conditional types apply conditions to whole types without splitting.
This leads to cleaner, safer, and easier-to-maintain code.
Practice
Solution
Step 1: Understand distributive conditional types
Distributive conditional types apply the condition to each member of a union type separately.Step 2: Understand non-distributive conditional types
Non-distributive conditional types evaluate the condition on the entire union type as a single entity, not distributing over members.Final Answer:
It evaluates the condition on the entire union type as a whole, not on each member separately. -> Option DQuick Check:
Non-distributive = whole union check [OK]
- Thinking conditional always distributes over unions
- Confusing non-distributive with type narrowing
- Assuming it only works on primitives
Solution
Step 1: Recognize non-distributive syntax
Wrapping the type parameter in a tuple, like [T], prevents distribution over unions.Step 2: Compare options
type NonDist<T> = [T] extends [string] ? true : false; uses [T] extends [string], which is the correct non-distributive syntax. type NonDist<T> = T extends string ? true : false; distributes over unions. Options C and D are invalid conditional syntax.Final Answer:
type NonDist<T> = [T] extends [string] ? true : false; -> Option CQuick Check:
Tuple wrapping disables distribution [OK]
- Not wrapping type in tuple, causing distribution
- Using invalid conditional syntax
- Confusing union with intersection in condition
type Test<T> = T extends string ? 'yes' : 'no'; type Result = Test<'a' | number>;
What is the type of
Result?Solution
Step 1: Understand distributive conditional types
SinceTis a union'a' | number, the condition distributes over each member.Step 2: Evaluate each member
'a' extends string is true, so 'yes'; number extends string is false, so 'no'. Combined result is 'yes' | 'no'.Final Answer:
'yes' | 'no' -> Option AQuick Check:
Distributes over union = 'yes' | 'no' [OK]
- Assuming whole union checked at once
- Expecting only 'yes' or only 'no'
- Confusing union with intersection
type NonDist<T> = T extends [string] ? true : false;
Solution
Step 1: Analyze the condition
The condition checks ifTextends[string], a tuple type, not wrappingT.Step 2: Understand distribution prevention
To prevent distribution,Titself must be wrapped in a tuple:[T] extends [string]. This code does not do that, so distribution is not prevented.Final Answer:
It incorrectly checks if T extends a tuple containing string, not preventing distribution. -> Option AQuick Check:
Wrap T, not string, to prevent distribution [OK]
- Wrapping the wrong side of extends
- Confusing tuple with type wrapper
- Assuming syntax error instead of logic error
T is exactly string | number (no more, no less)?Solution
Step 1: Prevent distribution with tuple wrapping
WrappingTin a tuple[T]prevents distribution over unions.Step 2: Use mutual assignability checks
Check[T] extends [string | number]and[string | number] extends [T]to ensure exact match, no extra or missing types.Final Answer:
type Exact<T> = [T] extends [string | number] ? ([string | number] extends [T] ? true : false) : false; -> Option BQuick Check:
Tuple wrap + mutual extends = exact type check [OK]
- Not preventing distribution, causing partial matches
- Checking only one extends direction
- Using incorrect tuple wrapping
Ready to prove it?
Pass the test and this pattern moves unknown
