Fixing the 'Source has X element(s) but target requires Y' TypeScript Error

beginner๐Ÿ”ต TypeScript2026-07-28| TypeScript 3.0+, Node.js, any OS (Windows, macOS, Linux), VS Code.

Error Message

Type '[string, number]' is not assignable to type '[string, number, boolean]'. Source has 2 element(s) but target requires 3.
#typescript#tuple#array#web-development

The ProblemTypeScript treats tuples like strict blueprints. Unlike standard arrays, which can grow or shrink, a tuple is a fixed-size collection where every position has a specific purpose. When you see this error, it means you're trying to fit a small piece of data into a slot designed for something larger.

Imagine you are defining a coordinate system for a 3D engine:

type Point3D = [number, number, number];

// Error: Source has 2 element(s) but target requires 3
const position: Point3D = [10, 20];

The compiler expects three numbers. Since you only provided two, it throws an error because the third element would technically be undefined, which doesn't match the number type required by your blueprint.

Root CauseBy default, TypeScript tuples have a hardcoded length property. If you define a tuple as [string, string], its length is exactly 2. Assigning an array with a length of 1 or 3 violates that contract. The compiler isn't just checking the data types; it is enforcing the structure of the container itself.

Solution 1: Use Optional Tuple ElementsDo you actually need that third value every single time? If some elements are only needed occasionally, mark them as optional using the ? symbol. This is the cleanest way to handle varying data lengths without losing type safety.

// The third element is now optional
type UserResponse = [string, number, boolean?];

const userA: UserResponse = ["Alice", 200, true]; // Works
const userB: UserResponse = ["Bob", 404];         // Also works

Keep in mind that optional elements must sit at the end of your tuple. You cannot place a required element after an optional one, as that would make the indexing ambiguous for the compiler.

Solution 2: Use Rest Elements for Dynamic LengthsSometimes you know how a list starts, but you have no idea how it ends. In these cases, use the rest operator (...) to allow for any number of additional elements. This effectively turns the end of your tuple into an open-ended array.

// Requires a status code and a message, then any number of tags
type LogEntry = [number, string, ...string[]];

const simpleLog: LogEntry = [200, "OK"];
const detailedLog: LogEntry = [500, "Error", "server", "database", "retry_failed"];

This is particularly useful for function arguments or when processing CSV-style data where the first few columns are fixed but the rest are variadic.

Solution 3: Type Assertion (The Quick Fix)If you are pulling data from an external API and you are 100% sure the structure is correct despite what the compiler thinks, you can use a type assertion. Treat this as a last resort. It tells TypeScript to "trust you," which bypasses the safety check entirely.

type Coordinates = [number, number, number];
const rawData = [1.5, 2.5] as unknown as Coordinates;

Use this sparingly. If the data actually is missing at runtime, your code might crash when it tries to access rawData[2], and TypeScript won't warn you about it.

Solution 4: Updating Function SignaturesYou might run into this when passing data to a function. If the function expects a three-item tuple but your data is dynamic, you should update the function signature to handle optional values. Destructuring with default values is a great way to handle this safely.

function setConfig(config: [string, number, boolean?]) {
    const [theme, version, isEnabled = true] = config;
    console.log(`Setting ${theme} v${version}. Active: ${isEnabled}`);
}

VerificationAfter applying a fix, verify your work with these three steps:

  • Check the Editor: Ensure the red squiggly lines in VS Code have vanished.- Run the Compiler: Execute npx tsc. A successful fix will result in a clean exit with no error messages.- Test Runtime Logic: If you used optional elements, ensure your logic doesn't break when that element is undefined.## Best Practices for PreventionAvoid these headaches in the future by following these patterns:
  • Prefer Objects: If your tuple has more than three elements, it's usually better to use an interface. Objects are more readable and don't rely on strict ordering.- Use Readonly: Use readonly [number, number] to prevent accidental .push() or .pop() calls that would change the tuple length during execution.- Explicit Returns: When creating custom React hooks that return arrays, always explicitly type the return as a tuple. Otherwise, TypeScript might infer it as a standard array, leading to length errors later.

Related Error Notes