How to fix Nested conditional type resolves to never in TypeScript
This TypeScript error occurs when nested conditional types create impossible type combinations that resolve to the 'never' type. The fix involves simplifying complex type logic, using distributive conditional types, or restructuring type definitions to avoid infinite recursion or impossible constraints.
Quick fix
Fixes Nested conditional type resolves to never
// Problematic example:
type DeepConditional<T> = T extends string
? T extends number // This can never be true if T extends string
? "impossible" // This branch resolves to never
: "string"
: "other";
// TypeScript error: Nested conditional type resolves to never- Identify the problematic conditional type
- Simplify nested conditional logic
- Use distributive conditional types carefully
- Avoid circular type references
// Problematic example:type DeepConditional<T> = T extends string? T extends number // This can never be true if T extends string? "impossible" // This branch resolves to never: "string": "other";// TypeScript error: Nested conditional type resolves to neverNested conditional type resolves to never
What this error means
The 'never' type in TypeScript represents an impossible state—a type with no values. When you see "Nested conditional type resolves to never", it means TypeScript's type inference has determined that your nested conditional types create a logical contradiction or infinite recursion. This typically happens with: 1. Deeply nested conditional types that create circular dependencies 2. Conditional types that reference themselves in a way that creates infinite expansion 3. Type constraints that become impossible to satisfy due to nested conditions 4. Distributive conditional types that eliminate all possible type parameters The error indicates that TypeScript cannot compute a meaningful type from your conditional type expression because it logically reduces to an impossible type (never). This is different from runtime errors—it's a compile-time type system limitation.
Typical symptoms
- TypeScript compiler error: 'Nested conditional type resolves to never'
- Type inference fails with complex conditional types
- Generic type parameters become 'never' unexpectedly
- Code completion stops working for affected types
- The error appears in type definitions, not runtime code
- Related to recursive or self-referential type definitions
- Occurs with deeply nested type utilities or mapped types
Common causes
- Circular type references in conditional types (most common)
- Infinite type expansion due to self-referential conditional types
- Impossible type constraints in nested conditions
- Distributive conditional types eliminating all union members
- Conditional types that always evaluate to false in nested contexts
- Type parameter constraints that become unsatisfiable
- Complex type transformations with multiple nested conditions
How to fix "Nested conditional type resolves to never"
First, locate the conditional type causing the issue. Look for deeply nested extends clauses:
// Problematic example:
type DeepConditional<T> = T extends string
? T extends number // This can never be true if T extends string
? "impossible" // This branch resolves to never
: "string"
: "other";
// TypeScript error: Nested conditional type resolves to neverUse your IDE's hover feature to see what TypeScript infers at each level. The error often appears in utility types or complex generic constraints.
Break down complex conditional types into simpler, non-nested forms:
// Before (problematic):
type Complex<T> = T extends string
? T extends `${infer _}${infer __}`
? "multi-char"
: "single-char"
: "not-string";
// After (simplified):
type StringCheck<T> = T extends string ? true : false;
type MultiCharCheck<T> = T extends `${infer _}${infer __}` ? true : false;
type Simplified<T> = StringCheck<T> extends true
? MultiCharCheck<T> extends true
? "multi-char"
: "single-char"
: "not-string";By separating concerns, you avoid the infinite recursion that causes 'never' resolution.
Conditional types distribute over union types. Ensure distribution doesn't eliminate all possibilities:
// Problem: Distribution eliminates all union members
type Problem<T> = T extends never ? "yes" : "no";
// Result: Problem<any> = never (distributes over empty union)
// Solution: Use non-distributive form with tuple
type Solution<T> = [T] extends [never] ? "yes" : "no";
// Result: Solution<any> = "no"
// Another example with nested distribution:
type DeepDistribute<T> = T extends string
? (T extends "a" | "b" ? "ab" : "other-string")
: "not-string";
// If T is never, this becomes never due to distributionWrap conditional types in tuples [T] extends [U] to prevent unwanted distribution.
Self-referential conditional types can cause infinite expansion:
// Circular reference causing infinite recursion:
type Circular<T> = T extends string ? Circular<T> : T;
// TypeScript: Nested conditional type resolves to never
// Solution: Add base case or limit recursion:
type LimitedCircular<T, Depth extends number = 3> =
Depth extends 0
? T // Base case to stop recursion
: T extends string
? LimitedCircular<T, Decrement<Depth>>
: T;
// Helper type to decrement (simplified):
type Decrement<N extends number> =
N extends 3 ? 2 : N extends 2 ? 1 : N extends 1 ? 0 : never;Always include termination conditions for recursive type definitions.
When conditional types become too complex, use inference to break them down:
// Complex nested conditional:
type ComplexNested<T> = T extends { data: infer D }
? D extends Array<infer Item>
? Item extends { id: string }
? Item["id"]
: never
: never
: never;
// Simplified with helper types:
type ExtractData<T> = T extends { data: infer D } ? D : never;
type ExtractArrayItem<T> = T extends Array<infer Item> ? Item : never;
type ExtractId<T> = T extends { id: infer Id } ? Id : never;
type SimplifiedNested<T> = ExtractId<ExtractArrayItem<ExtractData<T>>>;Breaking complex types into smaller, composable utilities makes them easier to debug.
Create test cases to verify your conditional types work correctly:
// Test your conditional type with concrete examples:
type Test1 = ComplexNested<{ data: [{ id: "abc" }, { id: "def" }] }>;
// Should be: "abc" | "def"
type Test2 = ComplexNested<{ data: string }>;
// Should be: never (not an array)
type Test3 = ComplexNested<{ other: true }>;
// Should be: never (no data property)
// Use TypeScript's type checking to verify:
const assert1: Test1 = "abc"; // Should work
const assert2: Test1 = "xyz"; // Should error
// Debug tool: Log inferred types
type Debug<T> = { [K in keyof T]: T[K] };
type DebugTest = Debug<Test1>; // Hover to see structureTesting helps identify where the 'never' resolution occurs in complex type chains.
Advanced notes
### Understanding Conditional Type Resolution
TypeScript's conditional types use a form of type-level computation. When you write T extends U ? X : Y, TypeScript:
1. Checks if T is assignable to U
2. If yes, returns X
3. If no, returns Y
4. If T is a union, distributes over each member (unless wrapped in tuple)
Nested conditional types create computation chains. When these chains:
- Reference themselves circularly → Infinite recursion → never
- Create impossible constraints → Logical contradiction → never
- Distribute over empty unions → No results → never
### The 'never' Type in Conditional Contexts
never is special in conditional types:
- never extends anything is true (bottom type property)
- anything extends never is false (except never itself)
- Conditional types distribute over never as an empty union
This leads to edge cases:
type Test1 = never extends string ? true : false; // true
type Test2 = string extends never ? true : false; // false
type Test3 = never extends never ? true : false; // true
// Distribution quirk:
type Distribute<T> = T extends string ? "yes" : "no";
type Result = Distribute<never>; // never (distributes over empty union)### Recursive Type Limits
TypeScript has practical limits on type recursion depth (around 50 levels). Exceeding this can cause:
- Performance issues
- "Type instantiation is excessively deep" errors
- Eventual resolution to 'never'
Solutions:
1. Use iteration instead of recursion when possible
2. Implement depth limits with counter types
3. Use mapped types for repetitive transformations
### Real-World Example: Deep Partial
A common pattern that can cause issues:
type DeepPartial<T> = {
[P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
};
// For recursive structures, this can cause infinite expansion
interface Node {
value: number;
children: Node[];
}
type PartialNode = DeepPartial<Node>; // May cause issuesFix: Add depth limit or use conditional check for arrays:
type DeepPartialSafe<T, Depth extends number = 5> =
Depth extends 0
? T
: {
[P in keyof T]?: T[P] extends Array<infer U>
? Array<DeepPartialSafe<U, Decrement<Depth>>>
: T[P] extends object
? DeepPartialSafe<T[P], Decrement<Depth>>
: T[P];
};### Performance Considerations
Complex conditional types impact:
- Compilation time (type checking phase)
- IDE responsiveness (IntelliSense, hover info)
- Language server performance
Best practices:
1. Cache complex types with type Alias = ComplexType<T>
2. Avoid unnecessary nesting
3. Use simpler alternatives when possible
4. Profile with tsc --diagnostics to identify slow types
Frequently asked questions
- What does "Nested conditional type resolves to never" mean?
- The 'never' type in TypeScript represents an impossible state—a type with no values. When you see "Nested conditional type resolves to never", it means TypeScript's type inference has determined that your nested conditional types create a logical contradiction or infinite recursion. This typically happens with: 1.
- How do I fix "Nested conditional type resolves to never"?
- This TypeScript error occurs when nested conditional types create impossible type combinations that resolve to the 'never' type. The fix involves simplifying complex type logic, using distributive conditional types, or restructuring type definitions to avoid infinite recursion or impossible constraints.
- What causes "Nested conditional type resolves to never"?
- Circular type references in conditional types (most common) Infinite type expansion due to self-referential conditional types Impossible type constraints in nested conditions
- Is the "Nested conditional type resolves to never" error serious?
- It is a medium-severity error — more of a blocker than a risk. The steps above resolve it.
Official resources & further reading
- 📚TypeScript Official Documentation
- 📖TypeScript Handbook: Conditional Types(Official Docs)
- 📖TypeScript 4.1 Release Notes: Template Literal Types(Official Docs)
- 🐙