Fixing TypeScript's 'Neither Type Sufficiently Overlaps' Error

intermediate🔵 TypeScript2026-04-29| TypeScript 3.0+ / Node.js / VS Code

Error Message

Conversion of type 'string' to type 'number' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
#typescript#type-assertion#type-mismatch#unknown#data-conversion

The Error Scenario

This error usually hits when you try to force a variable into a type it simply cannot be. TypeScript checks for 'overlap'—meaning, could these two types ever share common ground? If the answer is a hard 'no,' the compiler blocks the assertion to save you from nasty runtime bugs.

Let's look at a classic mistake where a developer tries to cast an API string directly to a number:

const priceInput = "49.99";

// This will trigger the error:
// Conversion of type 'string' to type 'number' may be a mistake...
const price = priceInput as number;

Analysis: Why TypeScript Is Blocking You

TypeScript allows type assertions (the as keyword) only if one type is a subtype of another. Think of it like a family tree. You can cast a generic HTMLElement to a specific HTMLButtonElement because a button is a type of element. They share common properties.

Primitives like string and number are different. They live on totally separate branches. A string like "123" is never literally the number 123 in the eyes of the compiler. Forcing as number on a string is essentially lying to the runtime. This lie leads to NaN results or app crashes during mathematical operations.

The Quick Fix: Double Casting

Sometimes you’re dealing with messy third-party data and you're 100% certain of the outcome. In those rare cases, you can bypass the safety check by using an intermediate cast to unknown. The error message even hints at this solution.

const priceInput = "49.99";

// Step 1: Cast to unknown (the 'top' type)
// Step 2: Cast to the target type
const price = (priceInput as unknown) as number;

Heads up: This clears the red squiggly line, but it doesn't change the data. At runtime, price is still the string "49.99". If you call price.toFixed(2), your app will crash because toFixed is a number method, not a string one.

The Permanent Fix: Real Data Transformation

Most of the time, you don't want a cast; you want a conversion. Casting asks the compiler to look the other way. Conversion actually changes the underlying value into the correct format.

Converting Strings to Numbers

Stick to standard JavaScript methods. They are safer and more readable:

const priceInput = "49.99";

// Option A: The Number constructor (Best for strict conversion)
const price = Number(priceInput); 

// Option B: parseFloat (Great for extracting decimals from messy strings)
const priceFloat = parseFloat(priceInput);

Fixing Object Incompatibility

Mapping functions are your best friend when dealing with mismatched interfaces. If an API returns a string ID but your UI needs a number, don't force it. Map it instead:

interface UserResponse {
  user_id: string; // e.g., "101"
  user_name: string;
}

interface AppUser {
  id: number; // e.g., 101
  name: string;
}

const rawData = { user_id: "101", user_name: "Alice" } as UserResponse;

// Map the data manually to ensure types match
const user: AppUser = {
  id: parseInt(rawData.user_id, 10),
  name: rawData.user_name
};

Handling "Incomplete" Objects in Tests

This error often pops up during unit testing. You might only want to mock a few fields of a massive interface. If you provide an object that is too small, TypeScript will complain that the types don't overlap.

Using Partial<T> is usually the cleanest fix. It tells TypeScript that you only intend to provide some of the properties, making the types 'overlap' again without resorting to unsafe casting.

Verification Checklist

Before you ship your code, verify the fix with these three steps:

  • Verify the Runtime Type: Add console.log(typeof price). It should print "number", not "string".
  • Try a Math Operation: Add 10 to your result. If "49.99" + 10 equals "49.9910", your cast 'worked' but your logic failed. If it equals 59.99, you're golden.
  • Check the Compiler: Run tsc --noEmit from your terminal. Ensure the error is gone for good.

Related Error Notes