How to Fix a JavaScript Number Concatenation Bug
String amounts summed with + silently concatenate instead of adding - '10' + '5' is '105', not 15. The fix is to coerce each value to a number before the sum. It's a silent bug: no error, just a wrong result.
Why + concatenates instead of adds
JavaScript's + operator is overloaded: when both operands are numbers it adds,
but when either operand is a string it concatenates. Form fields, query strings,
and JSON payloads from certain clients deliver values as strings - so + does the
wrong thing silently.
// All three values arrive as strings from a form or JSON body:
const amounts = ["10", "5", "3"];
const total = amounts[0] + amounts[1] + amounts[2];
// total === "1053" -- string concatenation, not addition
No exception is thrown. The endpoint returns something, just the wrong something - which makes this one of the harder bugs to notice without a targeted test.
The fix: coerce before you sum
Convert each value to a number before accumulating. Python and JavaScript both have the same trap; both have the same fix.
Python (Flask endpoint):
@app.post("/api/total")
def total():
amounts = (request.get_json(silent=True) or {}).get("amounts", [])
result = sum(int(a) for a in amounts)
return jsonify(total=result)
int(a) (or float(a)) converts each string before the sum - sum(...) then
adds numbers, not strings.
JavaScript equivalent:
const amounts = ["10", "5", "3"];
// Option 1: unary + (coerces to number)
const total = amounts.reduce((acc, a) => acc + +a, 0);
// Option 2: explicit Number()
const total2 = amounts.reduce((acc, a) => acc + Number(a), 0);
// Option 3: parseInt / parseFloat
const total3 = amounts.reduce((acc, a) => acc + parseInt(a, 10), 0);
Starting the accumulator at 0 (a number) is important: if you start with "" or
omit the initial value when the first element is a string, you're back to
concatenation.
Validate at the boundary
The most reliable defense is to validate and coerce incoming data the moment it enters your system - before any business logic runs:
- Python: use Pydantic. Declare
amounts: list[int]and Pydantic coerces and validates automatically - invalid values raise a422instead of silently producing a wrong result. - TypeScript: use Zod.
z.array(z.coerce.number())parses strings to numbers at the boundary. - Money: never use
floatfor currency. Represent amounts as integer cents (1050for $10.50) or use a decimal type (Decimalin Python) to avoid floating point rounding errors on top of the coercion bug.
Want to try it hands-on? HeyDevJob gives you this exact setup in a live cloud workspace in your browser - edit it, run it, and see it work. Free, nothing to install.
Try it in a workspace →What you'll practice
- Coercing string amounts to numbers before summing
- Using reduce with a numeric accumulator to avoid concatenation
- Validating API input types with Pydantic or Zod at the boundary
FAQ
Why does my JavaScript total concatenate instead of add?
Because the values are strings and the + operator concatenates strings. '10' + '5' === '105', not 15. Convert each value to a number (Number(), parseInt(), or unary +) before summing.
How do I sum an array of string numbers in JavaScript?
Use reduce with a numeric initial value: amounts.reduce((acc, a) => acc + Number(a), 0). The initial value of 0 ensures the accumulator starts as a number, not a string.
How do I prevent type coercion bugs in a web API?
Validate and coerce at the boundary using a schema library - Pydantic (Python) or Zod (TypeScript). Declare the expected type (e.g. list[int]) and let the library reject or coerce bad inputs before they reach your business logic.
Can you concatenate numbers in JavaScript?
Yes, and that is the trap: the + operator concatenates if either operand is a string, so '10' + 5 becomes '105'. To add, coerce to numbers first with Number(x) or parseFloat(x).
Keep learning
Learn it by doing. Open this in a live cloud workspace, make the change yourself, and keep a record of the work you can share.
Open the workspace →