How to fix Cannot extend with union type containing 'never' in TypeScript

TypeScriptADVANCEDMEDIUMUpdated Dec 10, 2025· 99 views

This TypeScript error occurs when using conditional types with union types that contain 'never', often in complex generic type transformations. The issue arises from how distributive conditional types handle the never type during union distribution. The fix typically involves wrapping types in tuples or adjusting type constraints.

Quick fix

Fixes Cannot extend with union type containing 'never'

// WRONG - Distributive conditional type causes issues with never
type IsString<T> = T extends string ? true : false;
type Result = IsString<string | never>; // May cause error

// CORRECT - Wrap in tuples to avoid distribution
type IsString<T> = [T] extends [string] ? true : false;
type Result = IsString<string | never>; // Works correctly
  1. Wrap types in tuples to avoid distribution
  2. Use generic context with infer to enable distribution
  3. Check if the union actually contains never
  4. Rewrite conditional types to handle never explicitly
typescript — error
// WRONG - Distributive conditional type causes issues with never
type IsString<T> = T extends string ? true : false;
type Result = IsString<string | never>; // May cause error
// CORRECT - Wrap in tuples to avoid distribution
type IsString<T> = [T] extends [string] ? true : false;
type Result = IsString<string | never>; // Works correctly
Cannot extend with union type containing 'never'

What this error means

The "Cannot extend with union type containing 'never'" error appears when TypeScript's type system encounters issues with distributive conditional types that include the 'never' type in a union. This is a relatively advanced error that typically occurs when working with complex generic type transformations, utility types, or mapped types. The 'never' type in TypeScript represents values that never occur - it's the bottom type in TypeScript's type hierarchy. In union types, 'never' normally gets filtered out automatically (similar to how zero works in addition). However, when used with conditional types that employ the 'extends' keyword, the presence of 'never' in a union can cause distribution problems. Distributive conditional types automatically distribute over union types during instantiation. When a union type is plugged into a conditional type, TypeScript applies the condition to each member of the union individually. If that union contains 'never' or resolves to 'never' in certain branches, TypeScript may raise this error when it cannot properly evaluate the extends constraint. Common scenarios include: 1. **Type filtering utilities**: Attempting to filter out types from a union using conditional types 2. **Generic constraints**: Using union types with 'never' as generic constraints 3. **Nested conditional types**: Complex type transformations where intermediate results include 'never' 4. **Distributive vs non-distributive behavior**: Confusion between how naked type parameters distribute versus wrapped types

Typical symptoms

  • TypeScript compilation fails with error mentioning 'never' in union types
  • Error appears when using generic utility types with conditional logic
  • Type errors in complex mapped types or conditional type transformations
  • Issues with type filtering or exclusion utilities (like Exclude<T, U>)
  • Error occurs when checking if a type extends a union containing never
  • Problems with distributive conditional types that resolve to never in some branches

Common causes

  1. Using naked type parameters in conditional types with unions containing never
  2. Attempting to extend or check constraints against a union that includes never
  3. Incorrect distribution behavior when filtering union types with conditional types
  4. Missing tuple wrapping around type parameters to prevent distribution
  5. Generic type parameter resolved to never causing constraint violations
  6. Using property access on conditional types (makes them non-distributive)
  7. Nested conditional types where intermediate results produce never unexpectedly

How to fix "Cannot extend with union type containing 'never'"

1Wrap types in tuples to avoid distribution

The most common fix is to wrap your type parameters in tuple brackets to prevent distributive behavior:

typescript
// WRONG - Distributive conditional type causes issues with never
type IsString<T> = T extends string ? true : false;
type Result = IsString<string | never>; // May cause error

// CORRECT - Wrap in tuples to avoid distribution
type IsString<T> = [T] extends [string] ? true : false;
type Result = IsString<string | never>; // Works correctly

This pattern prevents TypeScript from distributing the conditional type over each union member:

typescript
// Example: Filtering union types
type Filter<T, U> = [T] extends [U] ? T : never;

// Example: Checking for never
type IsNever<T> = [T] extends [never] ? true : false;
type Check1 = IsNever<never>;        // true
type Check2 = IsNever<string>;       // false

The tuple wrapping treats the entire union as a single unit rather than distributing over each member.

2Use generic context with infer to enable distribution

If you need distributive behavior but want to avoid the error, use a generic context with the 'infer' keyword:

typescript
// WRONG - Non-distributive comparison may fail
type ExtractString<T> = T extends string ? T : never;

// CORRECT - Use infer to create generic context
type ExtractString<T> = T extends infer U
  ? U extends string
    ? U
    : never
  : never;

// Example usage
type Result = ExtractString<string | number | boolean>;
// Result: string

This creates a conditional type with a generic parameter context, allowing iteration over union members:

typescript
// Filtering out null and undefined
type NonNullable<T> = T extends infer U
  ? U extends null | undefined
    ? never
    : U
  : never;

type Clean = NonNullable<string | null | number | undefined>;
// Clean: string | number
3Check if the union actually contains never

Verify whether your union type is unintentionally resolving to never:

typescript
// Debug helper to inspect types
type Debug<T> = { [K in keyof T]: T[K] };

// Check what your type resolves to
type MyUnion = string | never;
type Resolved = Debug<{ value: MyUnion }>;
// Hover over Resolved in your IDE to see: { value: string }

// Common case: Generic parameter that might be never
type SafeExtract<T, U> = T extends never
  ? never
  : T extends U
  ? T
  : never;

If your union contains never unintentionally, find where it's being produced:

typescript
// This produces never if no overlap exists
type Overlap<T, U> = Extract<T, U>;
type NoMatch = Overlap<string, number>; // never

// Fix by handling the never case explicitly
type SafeOverlap<T, U> = Extract<T, U> extends never
  ? "no overlap"
  : Extract<T, U>;
4Rewrite conditional types to handle never explicitly

Add explicit checks for the never type before performing extends operations:

typescript
// WRONG - Doesn't handle never case
type Transform<T> = T extends string ? string[] : T;

// CORRECT - Check for never first
type Transform<T> = [T] extends [never]
  ? never
  : T extends string
  ? string[]
  : T;

// Example with union filtering
type FilterOut<T, U> = T extends never
  ? never
  : T extends U
  ? never
  : T;

type Numbers = FilterOut<string | number | boolean, string | boolean>;
// Numbers: number

For complex transformations, break them into smaller steps:

typescript
// Multi-step type transformation
type Step1<T> = [T] extends [never] ? never : T;
type Step2<T> = Step1<T> extends string ? string[] : Step1<T>;
type Final<T> = Step2<T>;

type Result = Final<string>; // string[]
5Use built-in utility types when possible

TypeScript's built-in utilities handle never correctly. Use them instead of custom implementations:

typescript
// Instead of custom filters, use built-ins
type OnlyStrings = Extract<string | number | boolean, string>;
// OnlyStrings: string

type NotStrings = Exclude<string | number | boolean, string>;
// NotStrings: number | boolean

type NoNulls = NonNullable<string | null | undefined>;
// NoNulls: string

// Combining utilities
type SafePick<T, K extends keyof T> = {
  [P in K]: NonNullable<T[P]>;
};

interface User {
  name: string;
  email: string | null;
  age: number | undefined;
}

type RequiredUser = SafePick<User, "name" | "email">;
// { name: string; email: string }

These utilities are battle-tested and handle edge cases with never automatically.

6Adjust generic constraints to prevent never

If the error occurs at the constraint level, modify your generic constraints:

typescript
// WRONG - Constraint may include never
function process<T extends string | never>(value: T): void {
  // Error: Cannot extend with union type containing 'never'
}

// CORRECT - Remove never from constraint
function process<T extends string>(value: T): void {
  // Works correctly
}

// Or handle it explicitly
function process<T>(value: T extends never ? string : T): void {
  // Explicit never handling
}

// For conditional constraints
type ValidKeys<T> = {
  [K in keyof T]: T[K] extends Function ? never : K;
}[keyof T];

// Use with an object type
interface Config {
  name: string;
  getValue: () => string;
  timeout: number;
}

type DataKeys = ValidKeys<Config>;
// DataKeys: "name" | "timeout" (excludes getValue)

Advanced notes

### Understanding Distributive Conditional Types

Distributive conditional types are a key feature of TypeScript's type system. They work differently depending on whether the checked type is a "naked type parameter":

Distributive (naked type parameter):

typescript
type ToArray<T> = T extends any ? T[] : never;
type Result = ToArray<string | number>;
// Distributes: (string extends any ? string[] : never) | (number extends any ? number[] : never)
// Result: string[] | number[]

Non-distributive (wrapped type parameter):

typescript
type ToArray<T> = [T] extends [any] ? T[] : never;
type Result = ToArray<string | number>;
// No distribution: checks (string | number) as whole
// Result: (string | number)[]

### The Never Type's Special Behavior

The 'never' type has unique properties in TypeScript:

1. Union elimination: string | never simplifies to string
2. Intersection dominance: string & never results in never
3. Empty set: Represents the type of values that never occur
4. Bottom type: Subtype of every other type

When 'never' appears in conditional types:

typescript
// never distributes to never
type Dist<T> = T extends any ? T[] : never;
type Result = Dist<never>; // never (not never[])

// This is because distributive types distribute over never's zero members
// For each member in never (none), apply the transformation = never

### Common Patterns and Solutions

Pattern 1: Type filtering with never

typescript
// Filter out types from a union
type Filter<T, U> = T extends U ? never : T;
type NonString = Filter<string | number | boolean, string>;
// NonString: number | boolean

Pattern 2: Detecting never

typescript
// Standard approach (doesn't work with distribution)
type IsNever<T> = T extends never ? true : false;
type Test = IsNever<never>; // never (not true!)

// Correct approach (prevents distribution)
type IsNever<T> = [T] extends [never] ? true : false;
type Test = IsNever<never>; // true ✓

Pattern 3: Exhaustiveness checking

typescript
type Status = "pending" | "approved" | "rejected";

function handleStatus(status: Status): string {
  switch (status) {
    case "pending":
      return "Waiting";
    case "approved":
      return "Done";
    case "rejected":
      return "Failed";
    default:
      // If Status gains new member, this will error
      const _exhaustive: never = status;
      return _exhaustive;
  }
}

### NoInfer and Union Distribution

TypeScript 5.4+ introduced the NoInfer utility type which prevents type inference in certain contexts. Be aware that distributive conditional types can't distribute over NoInfer types wrapping a union:

typescript
type Dist<T> = T extends string ? true : false;

// This works
type Test1 = Dist<string | number>; // boolean

// This may cause issues in complex scenarios
type Test2<T> = Dist<NoInfer<T>>;

### Debugging Type Errors

When encountering this error, use these techniques to debug:

1. Hover inspection: Hover over types in your IDE to see what they resolve to
2. Type assertions: Use helper types to inspect intermediate results:

typescript
type Inspect<T> = T extends infer U ? { type: U } : never;
type Result = Inspect<YourComplexType>;

3. Simplify gradually: Break complex conditional types into smaller, testable pieces
4. Use TypeScript playground: Test isolated type transformations at [typescriptlang.org/play](https://www.typescriptlang.org/play)

### When to Avoid Conditional Types

Sometimes simpler alternatives exist:

typescript
// Instead of complex conditional types
type Complex<T> = T extends string
  ? string[]
  : T extends number
  ? number[]
  : never;

// Consider overloading or union types
type Simple = string[] | number[];

Frequently asked questions

What does "Cannot extend with union type containing 'never'" mean?
The "Cannot extend with union type containing 'never'" error appears when TypeScript's type system encounters issues with distributive conditional types that include the 'never' type in a union. This is a relatively advanced error that typically occurs when working with complex generic type transformations, utility types, or mapped types. The 'never' type in TypeScript represents values that never occur - it's the bottom type in TypeScript's type hierarchy.
How do I fix "Cannot extend with union type containing 'never'"?
This TypeScript error occurs when using conditional types with union types that contain 'never', often in complex generic type transformations. The issue arises from how distributive conditional types handle the never type during union distribution. The fix typically involves wrapping types in tuples or adjusting type constraints.
What causes "Cannot extend with union type containing 'never'"?
Using naked type parameters in conditional types with unions containing never Attempting to extend or check constraints against a union that includes never Incorrect distribution behavior when filtering union types with conditional types
Is the "Cannot extend with union type containing '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