The TypeScript compiler is complaining because it encountered an expression where it expected a numeric value (like an integer or a floating-point number) but found something else, and it doesn’t know how to perform an arithmetic operation on that "something else."

This error, TS2363: The right side of an arithmetic operation must be a number, typically pops up when you’re trying to use operators like +, -, *, /, or % with operands that TypeScript can’t definitively classify as numbers. This can happen in several scenarios, often due to implicit type coercions, incorrect function return types, or misunderstandings about how JavaScript (and by extension, TypeScript) handles certain values.

Here are the most common culprits and how to fix them:

  1. String Literals or Variables Holding Strings: You might be accidentally trying to add a number to a string, or vice-versa, and TypeScript is catching it before runtime. JavaScript’s + operator is overloaded: it performs addition for numbers but concatenation for strings. When TypeScript sees a potential ambiguity or a clear string on the "right side" of an arithmetic operator other than +, it flags it.

    • Diagnosis: Hover over the variable or expression on the right side of the operator in your IDE. If it shows string, that’s your problem.
    • Fix: Explicitly convert the string to a number. If the string is guaranteed to be a valid number representation, use parseInt(), parseFloat(), or the unary plus operator (+).
      let quantity: string = "10";
      let price: number = 5;
      // Incorrect: let total = price + quantity; // TS2363
      let total: number = price + parseInt(quantity, 10); // Fix: Use parseInt
      // Or: let total: number = price + +quantity; // Fix: Use unary plus
      
    • Why it works: parseInt("10", 10) converts the string "10" into the number 10, allowing the + operator to perform numeric addition. The unary plus (+) attempts to convert its operand to a number, achieving the same result for valid numeric strings.
  2. undefined or null Values: If a variable might be undefined or null and you try to use it in an arithmetic operation, TypeScript will throw this error because undefined and null are not numbers.

    • Diagnosis: Check the type annotation of the variable. If it’s number | undefined or number | null, and you’re not checking for these values, this is likely the cause.
    • Fix: Add a check to ensure the value is not null or undefined before performing the arithmetic, or provide a default value.
      let stockCount: number | undefined = getStockCount(); // Might return undefined
      let reorderThreshold: number = 5;
      
      // Incorrect: if (stockCount < reorderThreshold) { ... } // TS2363 if stockCount is undefined
      let currentStock: number = stockCount ?? 0; // Fix: Use nullish coalescing for default
      if (currentStock < reorderThreshold) {
          console.log("Reorder needed!");
      }
      
    • Why it works: The nullish coalescing operator (??) provides a default value (0 in this case) if stockCount is null or undefined, ensuring the currentStock variable is always a number.
  3. Boolean Values: While JavaScript often coerces booleans to numbers (true to 1, false to 0) in arithmetic operations, TypeScript is stricter. It will prevent you from directly using booleans in arithmetic unless explicitly converted.

    • Diagnosis: If you’re using a variable that could be true or false in an arithmetic expression.
    • Fix: Explicitly convert the boolean to a number.
      let isComplete: boolean = true;
      let score: number = 10;
      
      // Incorrect: let finalScore = score + isComplete; // TS2363
      let finalScore: number = score + Number(isComplete); // Fix: Use Number() constructor
      
    • Why it works: Number(true) explicitly converts the boolean true to the number 1, allowing for correct numeric addition.
  4. Function Return Types Not Explicitly number: If a function is supposed to return a number but its return type is inferred as any, unknown, or even string (e.g., if it accidentally returns a stringified number), you might get this error when using its result in arithmetic.

    • Diagnosis: Check the return type of the function being called. If it’s not explicitly number, or if it’s any and the actual return value is not a number.
    • Fix: Ensure the function’s return type is accurately declared as number and that the function actually returns a number.
      function getNumericValue(): string { // Incorrect return type
          return "42";
      }
      // Fix 1: Change function signature and implementation
      // function getNumericValue(): number {
      //     return 42;
      // }
      
      let value: number = 10;
      // Incorrect: let result = value + getNumericValue(); // TS2363
      let result: number = value + parseInt(getNumericValue(), 10); // Fix: Parse the stringified number
      
    • Why it works: By either ensuring the function returns a number directly or by parsing the returned string into a number before use, you satisfy TypeScript’s type requirements for arithmetic operations.
  5. Object Properties or Array Elements with Non-Numeric Types: Similar to other cases, if you access a property of an object or an element of an array that is not a number, and then use it in an arithmetic operation.

    • Diagnosis: Inspect the type of the object property or array element you are using.
    • Fix: Ensure the property or element holds a number, or convert it if necessary.
      interface Item {
          id: number;
          quantity: string; // Quantity stored as string
      }
      let item: Item = { id: 1, quantity: "5" };
      let shippingCostPerItem: number = 2;
      
      // Incorrect: let totalShippingCost = item.quantity * shippingCostPerItem; // TS2363
      let totalShippingCost: number = parseInt(item.quantity, 10) * shippingCostPerItem; // Fix: Parse quantity
      
    • Why it works: parseInt(item.quantity, 10) converts the string "5" to the number 5, enabling multiplication with shippingCostPerItem.
  6. Type Assertions Used Incorrectly: If you’ve used a type assertion (as number) but the underlying value is not actually a number at runtime, you can still encounter runtime errors, but TypeScript might catch the type mismatch at compile time with TS2363 if the assertion is on the "right side" of an arithmetic operator and the inferred type is not compatible.

    • Diagnosis: Look for as number assertions in your code, especially around arithmetic operations.
    • Fix: Remove the incorrect assertion or ensure the value being asserted is a number. If you’re asserting a string that should be a number, use parseInt or parseFloat instead of as number.
      let rawValue: unknown = "7";
      let baseValue: number = 3;
      
      // Incorrect: let sum = baseValue + (rawValue as number); // TS2363 if rawValue is not actually a number
      let sum: number = baseValue + Number(rawValue); // Fix: Use Number() or parseInt/parseFloat for conversion
      
    • Why it works: Number(rawValue) correctly converts the string "7" to the number 7. Using as number on a string would tell TypeScript "trust me, this is a number," but it wouldn’t perform the actual conversion, leading to potential runtime issues or, in this specific case, a compile-time error if TypeScript can infer the string type.

After addressing these common causes, the next error you might encounter, particularly if you were dealing with string concatenation using +, is TS2365: Operator '+' cannot be applied to types 'number' and 'string'. This happens when you’ve fixed a TS2363 by ensuring the right side is a number, but the left side is still a string, and you intended concatenation.

Want structured learning?

Take the full Typescript course →