How to fix Type 'any' is not assignable to type 'never' in TypeScript

TypeScriptINTERMEDIATEMEDIUMUpdated Dec 11, 2025ยท 142 views

This error means TypeScript inferred the bottom type <code>never</code> for a branch or position but you are assigning an <code>any</code> value to it. The compiler rejects it because <code>never</code> explicitly represents no possible values.

Quick fix

Fixes Type 'any' is not assignable to type 'never'

  1. Find the branch that became <code>never</code>
  2. Widen the computed type instead of forcing <code>any</code>
  3. Narrow the <code>any</code> before handing it to the <code>never</code> branch
  4. Adjust your generics/utility to avoid empty unions
  5. Rely on exhaustive checking only for unreachable code
typescript โ€” error
# Type 'any' is not assignable to type 'never'
Type 'any' is not assignable to type 'never'

What this error means

TypeScript uses <code>never</code> to label unreachable code paths and the base of every strict union. When a branch collapses to <code>never</code>, the compiler assumes there is no valid value for that location. Passing <code>any</code> there defeats that assumption, so TypeScript refuses to treat <code>any</code> as a legal value. The most common time this pops up is during exhaustive switches, conditional checks that drop every union member, or when a generic constraint resolves to an empty union. The fix is either to widen the branch (so it no longer becomes <code>never</code>) or give <code>any</code> a real union type before pushing it through the narrow branch.

Typical symptoms

  • TS2322 / TS2345 in the terminal or IDE at the offending assignment or return statement
  • Red underlines on a call to an <code>assertNever</code> helper or the default case of a switch
  • The compiler thinks a discriminated union branch can never run, even though runtime data is flowing through it
  • Nullable/optional generic arguments collapse the target type to <code>never</code>
  • Having to cast through <code>as never</code> before the error goes away, even though the code runs fine

Common causes

  1. An exhaustive switch or <code>assertNever()</code> helper narrows every branch out of existence, leaving only <code>never</code> to satisfy the default case
  2. A generic helper or utility type returns <code>never</code> because the union of possible inputs was emptied by <code>Exclude</code>/<code>Extract</code>
  3. A typed tuple, array, or object literal is declared with <code>as const</code> and the inferred members collapse to <code>never</code>
  4. You are assigning API data, form values, or any value typed as <code>any</code> into a discriminated union that has no matching case
  5. The compiler can only see a <code>never</code> branch where it expects a real type, so feeding it <code>any</code> trips the error

How to fix "Type 'any' is not assignable to type 'never'"

1Find the branch that became <code>never</code>

Look at the stack trace or IDE squiggles and identify the control flow that collapsed to <code>never</code>. Common suspects are the <code>default</code> clause of a discriminated union switch, the result of <code>Extract</code> on an empty union, or a generic inference with no valid candidates. Hovering the expression should show <code>never</code> in the tooltip.

2Widen the computed type instead of forcing <code>any</code>

Give the variable a union that actually contains the value you are assigning. For example, change the signature of your helper from <code>function assertNever(x: never)</code> to accept the union or guard against <code>any</code> before calling it. Annotate arrays or tuples with the expected element type (e.g., <code>const values: Payload[] = []</code>), so TypeScript stops inferring an empty tuple that resolves to <code>never</code> after a push.

3Narrow the <code>any</code> before handing it to the <code>never</code> branch

Use type guards, discriminated unions, or helper functions to assert the real union for the <code>any</code> value. Don't blindly pass <code>any</code> into <code>assertNever</code>; instead narrow it with <code>if (typeof payload === "string")</code> or <code>switch</code> statements so the compiler can see a real type rather than <code>any</code>. If you still need to opt out, wrap the conversion in a single <code>as unknown as RealUnion</code> near the source, not at the <code>never</code> branch.

4Adjust your generics/utility to avoid empty unions

If the error comes from a conditional type, make sure the constraint produces an actual branch. For example, don't drop every variant with <code>Exclude<T, U></code> before you use it. Add default generics, fallback branches, or widen the pattern so <code>T</code> cannot resolve to <code>never</code> when meaningful data is provided.

5Rely on exhaustive checking only for unreachable code

When you intentionally use <code>never</code> to guard unreachable cases, wrap the helper in a clear assertion helper (e.g., <code>function assertNever(x: never): never</code>). Provide a typed fallback in the caller or wrap the <code>any</code> value with a safe union before it reaches <code>assertNever</code>. Don't sprinkle <code>any</code> all the way through your control flow; keep the <code>never</code> catch-all reserved for compile-time exhaustiveness checks.

Advanced notes

The TypeScript Handbook explains that <code>never</code> is assignable to every type, but no type is assignable back to <code>never</code> except <code>never</code> itself. That means TypeScript treats a <code>never</code> branch as impossible at runtime. If you see <code>any</code> pushed into a <code>never</code> slot, consider why the compiler thinks the branch is unreachable and fix the surrounding union or control flow instead of forcing <code>any</code>. When you trigger this error inside an <code>assertNever()</code> helper, it usually means you tried to test a branch that genuinely can still run at runtime. Adjust the helper or the argument so the compiler can prove the case is impossible before handing it to <code>never</code>.

Frequently asked questions

What does "Type 'any' is not assignable to type 'never'" mean?
TypeScript uses <code>never</code> to label unreachable code paths and the base of every strict union. When a branch collapses to <code>never</code>, the compiler assumes there is no valid value for that location. Passing <code>any</code> there defeats that assumption, so TypeScript refuses to treat <code>any</code> as a legal value.
How do I fix "Type 'any' is not assignable to type 'never'"?
This error means TypeScript inferred the bottom type <code>never</code> for a branch or position but you are assigning an <code>any</code> value to it. The compiler rejects it because <code>never</code> explicitly represents no possible values.
What causes "Type 'any' is not assignable to type 'never'"?
An exhaustive switch or <code>assertNever()</code> helper narrows every branch out of existence, leaving only <code>never</code> to satisfy the default case A generic helper or utility type returns <code>never</code> because the union of possible inputs was emptied by <code>Exclude</code>/<code>Extract</code> A typed tuple, array, or object literal is declared with <code>as const</code> and the inferred members collapse to <code>never</code>
Is the "Type 'any' is not assignable to 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