The never type in TypeScript: how to fix the "not assignable to parameter" error

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Introduction: why does TypeScript complain about an empty array?

\n\n

Have you ever written TypeScript code, run the compilation, and received a mysterious message: "Argument of type 'X' is not assignable to parameter of type 'never'"? If so, you are not alone. This error is a real stumbling block for developers of all levels. On Stack Overflow, this question has gathered thousands of views, and today we will break it down once and for all.

\n\n

Imagine this scenario: you declare an empty array, try to add something to it, and TypeScript blocks the operation. Sound familiar? Let's figure out why this happens and, most importantly, how to fix it.

\n\n

In this article, we won't just translate dry documentation. We will walk through the journey from the error's appearance to its complete resolution with real examples that you can immediately apply in your projects.

\n\n

What is the never type in TypeScript?

\n\n

Before diving into the intricacies of the error, let's understand the never type itself. In TypeScript, this type denotes "a value that cannot exist". It sounds philosophical, but in practice it's simple:

\n\n
    \n
  • never is the type for functions that never finish (infinite loop) or always throw an exception.
  • \n
  • never is the "bottom" of the type system. You can assign never to anything, but nothing can be assigned to never (except never itself).
  • \n
\n\n

Now imagine that TypeScript sees an empty array and doesn't know what elements it will contain. In strict typing mode (strict: true in tsconfig.json), the compiler makes a logical deduction: "If the array is empty and the type is not specified, then nothing can be in it — the element type is never".

\n\n
// Example: TypeScript infers the type as never[]\nconst emptyArray = [];\nemptyArray.push("hello"); // Error!\n// Argument of type 'string' is not assignable to parameter of type 'never'\n
\n\n

There it is, that very error. TypeScript honestly warns: "You said the array can only contain never, but you're trying to add a string. That won't work!"

\n\n

Main scenarios for the error occurrence

\n\n

1. Empty array without a type annotation

\n\n

The most common case. A developer creates an empty array, planning to fill it later, but forgets to specify the type.

\n\n
// ❌ Problem\nconst items = []; // TypeScript infers: any[] (if strict: false) or never[] (if strict: true)\nitems.push({ id: 1, name: "Alice" }); // Error when strict: true\n\n// ✅ Solution: explicitly specify the type\nconst items: Array<{ id: number; name: string }> = [];\nitems.push({ id: 1, name: "Alice" }); // Works!\n
\n\n

2. Array methods returning never (filter, reduce)

\n\n

The filter method with an incorrect predicate or reduce without an initial value can lead to the inference of the never type.

\n\n
// ❌ Problem with filter\nconst numbers: (number | null)[] = [1, null, 2, null, 3];\nconst onlyNumbers = numbers.filter(item => item !== null); \n// TypeScript may infer the type as (number | null)[] or even never[], if the predicate is "broken"\n\n// ✅ Solution: use a type guard\nconst onlyNumbersSafe: number[] = numbers.filter((item): item is number => item !== null); \n\n// ❌ Problem with reduce\nconst result = [1, 2, 3].reduce((acc, val) => acc + val); \n// Error! TypeScript doesn't know the initial accumulator type\n\n// ✅ Solution: specify the initial value\nconst resultSafe = [1, 2, 3].reduce((acc, val) => acc + val, 0); // Works!\n
\n\n

3. Generics and conditional types

\n\n

A more complex case is when TypeScript cannot infer the type due to complex generics.

\n\n
// ❌ Problem\nfunction getFirstElement<T>(arr: T[]): T | undefined {\n  return arr[0];\n}\n\nfunction processItems<T>                

Blogs

Book Recommendations