How to fix Property 'x' cannot be accessed on type 'never' in TypeScript

TypeScriptINTERMEDIATEMEDIUMUpdated Dec 11, 2025· 103 views

This TypeScript error occurs when you try to access a property on a value that TypeScript has determined can never exist at runtime. It typically happens with incomplete union type handling or exhaustive checks. The fix involves proper type narrowing and handling all possible cases.

Quick fix

Fixes Property 'x' cannot be accessed on type 'never'

type Status = 'pending' | 'success' | 'error';

function handleStatus(status: Status) {
  if (status === 'pending') {
    console.log('Processing...');
  } else if (status === 'success') {
    console.log('Done!');
  }
  // TypeScript knows status is 'never' here - 'error' case not handled
  console.log(status); // Error: Property 'length' cannot be accessed on type 'never'
}
  1. Identify the union type and missing cases
  2. Add exhaustive checking with assertNever pattern
  3. Handle all union cases explicitly
  4. Use proper type guards and narrowing
typescript — error
type Status = 'pending' | 'success' | 'error';
function handleStatus(status: Status) {
if (status === 'pending') {
console.log('Processing...');
} else if (status === 'success') {
console.log('Done!');
}
// TypeScript knows status is 'never' here - 'error' case not handled
console.log(status); // Error: Property 'length' cannot be accessed on type 'never'
}
Property 'x' cannot be accessed on type 'never'

What this error means

The TypeScript error "Property 'x' cannot be accessed on type 'never'" occurs when TypeScript's type system determines that a particular code path should be unreachable, yet you're trying to access properties on a value in that path. The 'never' type represents values that never occur—it's TypeScript's way of saying "this should never happen." When you see this error, TypeScript is telling you that based on its type analysis, the variable in question should have no possible values at that point in your code. This commonly happens with: 1. **Union types with unhandled cases**: When you have a union type like `A | B | C` but only handle some of the cases 2. **Exhaustive checks**: In switch statements or if/else chains where not all possibilities are covered 3. **Type narrowing**: When type guards eliminate all possible types before a certain point The error is TypeScript's way of catching logical errors in your code before runtime. If a value truly has type 'never', accessing any property on it would indeed be impossible at runtime.

Typical symptoms

  • TypeScript compiler error: "Property 'x' cannot be accessed on type 'never'"
  • Error appears in conditional branches (if/else, switch statements)
  • Occurs with union types when not all cases are handled
  • Happens after type narrowing eliminates all possible types
  • Common in exhaustive pattern matching implementations
  • May appear with discriminated unions missing cases

Common causes

  1. Missing case in switch statement with union types (most common)
  2. Incomplete if/else chain for union type handling
  3. Type predicate that doesn't cover all possibilities
  4. Discriminated union without handling all discriminant values
  5. Using type assertions that incorrectly narrow types
  6. Forgetting to handle the "default" case in exhaustive checks
  7. TypeScript's control flow analysis determining unreachable code

How to fix "Property 'x' cannot be accessed on type 'never'"

1Identify the union type and missing cases

First, locate where the 'never' type appears. Check what union type is involved and which cases are missing:

typescript
type Status = 'pending' | 'success' | 'error';

function handleStatus(status: Status) {
  if (status === 'pending') {
    console.log('Processing...');
  } else if (status === 'success') {
    console.log('Done!');
  }
  // TypeScript knows status is 'never' here - 'error' case not handled
  console.log(status); // Error: Property 'length' cannot be accessed on type 'never'
}

Hover over the variable in your IDE to see what type TypeScript infers. The error location shows where TypeScript thinks the code is unreachable.

2Add exhaustive checking with assertNever pattern

Implement the standard assertNever function for exhaustive checks:

typescript
function assertNever(value: never): never {
  throw new Error(`Unhandled value: ${value}`);
}

type Status = 'pending' | 'success' | 'error';

function handleStatus(status: Status) {
  switch (status) {
    case 'pending':
      console.log('Processing...');
      break;
    case 'success':
      console.log('Done!');
      break;
    case 'error':
      console.log('Error occurred');
      break;
    default:
      assertNever(status); // Type-safe exhaustive check
  }
}

This pattern ensures you handle all cases. If you add a new value to the Status union and forget to handle it, TypeScript will error at the assertNever call.

3Handle all union cases explicitly

For if/else chains, ensure every possible value is covered:

typescript
type Result = { type: 'data'; value: string } | { type: 'error'; message: string };

function processResult(result: Result) {
  if (result.type === 'data') {
    console.log(`Data: ${result.value}`);
  } else if (result.type === 'error') {
    console.log(`Error: ${result.message}`);
  }
  // All cases covered - no 'never' type
}

With discriminated unions (unions with a common property like type), TypeScript can narrow the type automatically in each branch.

4Use proper type guards and narrowing

Define explicit type guards for complex narrowing:

typescript
interface Circle { kind: 'circle'; radius: number }
interface Square { kind: 'square'; side: number }
interface Triangle { kind: 'triangle'; base: number; height: number }

type Shape = Circle | Square | Triangle;

function getArea(shape: Shape): number {
  if (shape.kind === 'circle') {
    return Math.PI * shape.radius ** 2;
  } else if (shape.kind === 'square') {
    return shape.side ** 2;
  } else if (shape.kind === 'triangle') {
    return 0.5 * shape.base * shape.height;
  }

  // This should be unreachable if all cases are handled
  const exhaustiveCheck: never = shape;
  return exhaustiveCheck;
}

The exhaustiveCheck variable forces TypeScript to verify all cases are handled.

5Check for implicit any conversions

Sometimes TypeScript converts 'never' to 'any' implicitly. Enable strict mode to catch these:

json
// tsconfig.json
{
  "compilerOptions": {
    "strict": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "strictFunctionTypes": true,
    "strictBindCallApply": true,
    "strictPropertyInitialization": true,
    "noImplicitThis": true,
    "alwaysStrict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true
  }
}

Strict mode prevents implicit 'any' conversions and catches more type errors.

6Review control flow and early returns

Check if early returns or throws affect type narrowing:

typescript
type Response = { ok: true; data: string } | { ok: false; error: string };

function handleResponse(response: Response): string {
  if (!response.ok) {
    throw new Error(response.error); // Early throw
  }

  // TypeScript knows response.ok is true here
  return response.data.toUpperCase(); // No error - properly narrowed
}

TypeScript tracks control flow and understands that after the throw, response.ok must be true. Make sure your control flow logic matches TypeScript's understanding.

Advanced notes

### Understanding TypeScript's 'never' Type

The 'never' type is TypeScript's bottom type—it represents a value that never occurs. Key characteristics:
- No values are assignable to 'never'
- 'never' is assignable to every type
- Functions that never return have return type 'never'
- Type narrowing produces 'never' when all possibilities are eliminated

### Exhaustiveness Checking Patterns

1. assertNever Function: The standard pattern shown above
2. Exhaustive Switch: Using default case with type assertion
3. Satisfies Operator (TypeScript 4.9+): shape satisfies never in default case

### Common Pitfalls

1. Single-member unions: TypeScript sometimes doesn't narrow single-value unions to 'never'
2. any/unknown conversions: With strict: false, 'never' may convert to 'any' silently
3. Generic constraints: Generic types with constraints may not narrow properly
4. Mapped types: Complex mapped types can produce unexpected 'never' results

### Real-world Example: API Response Handling

typescript
type ApiResponse<T> =
  | { status: 'success'; data: T }
  | { status: 'error'; code: number; message: string }
  | { status: 'loading' };

function handleApiResponse<T>(response: ApiResponse<T>): T | null {
  switch (response.status) {
    case 'success':
      return response.data;
    case 'error':
      console.error(`${response.code}: ${response.message}`);
      return null;
    case 'loading':
      console.log('Loading...');
      return null;
    default:
      // Type-safe exhaustive check
      const _exhaustiveCheck: never = response;
      return _exhaustiveCheck;
  }
}

### Performance Considerations

TypeScript's control flow analysis for 'never' is compile-time only—no runtime cost. The assertNever pattern adds minimal runtime overhead only when there's a bug (unhandled case).

### Testing Exhaustiveness

Write tests that verify all union cases are handled:

typescript
// Test that all Status values are handled
const statuses: Status[] = ['pending', 'success', 'error'];
statuses.forEach(status => {
  expect(() => handleStatus(status)).not.toThrow();
});

Frequently asked questions

What does "Property 'x' cannot be accessed on type 'never'" mean?
The TypeScript error "Property 'x' cannot be accessed on type 'never'" occurs when TypeScript's type system determines that a particular code path should be unreachable, yet you're trying to access properties on a value in that path. " When you see this error, TypeScript is telling you that based on its type analysis, the variable in question should have no possible values at that point in your code. This commonly happens with: 1.
How do I fix "Property 'x' cannot be accessed on type 'never'"?
This TypeScript error occurs when you try to access a property on a value that TypeScript has determined can never exist at runtime. It typically happens with incomplete union type handling or exhaustive checks. The fix involves proper type narrowing and handling all possible cases.
What causes "Property 'x' cannot be accessed on type 'never'"?
Missing case in switch statement with union types (most common) Incomplete if/else chain for union type handling Type predicate that doesn't cover all possibilities
Is the "Property 'x' cannot be accessed on type '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