Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions src/operators/binary/arithmetic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,21 @@ export function add(a: any, b: any): any {
return a + b;
}

// If both values are strings and at least one of them is a non-number
// then we want to concatenate the strings.
if (typeof a === 'string' && typeof b === 'string') {
// If one of the values is a string and both are either string or number, try to add or else concatenate.
if (
(typeof a === 'string' || typeof b === 'string') &&
(typeof a === 'string' || typeof a === 'number') &&
(typeof b === 'string' || typeof b === 'number')
) {
const numA = Number(a);
const numB = Number(b);

if (isNaN(numA) || isNaN(numB)) {
return `${a}${b}`;
}

// If both values can be converted to numbers then we want to add the numbers.
return numA + numB;
}

// If both values are arrays then we want to concatenate the arrays.
Expand All @@ -40,11 +46,6 @@ export function add(a: any, b: any): any {
return { ...a, ...b };
}

Copilot AI Jan 23, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By removing the numeric-coercion fallback (previously adding when both operands could be converted via Number()), expressions like true + 1 / 1 + true will now hit the final throw. This breaks existing behavior covered by tests (test/functions/functions-binary-ops.ts:52-57). Reintroduce the numeric conversion branch (after the array/object cases so null + null still merges to {}) to keep boolean/number (and similar) additions working.

Suggested change
// As a fallback, if both values can be converted to numbers then add the numbers.
const numA = Number(a);
const numB = Number(b);
if (!isNaN(numA) && !isNaN(numB)) {
return numA + numB;
}

Copilot uses AI. Check for mistakes.
// If both values can be converted to numbers then we want to add the numbers.
if (!isNaN(Number(a)) && !isNaN(Number(b))) {
return Number(a) + Number(b);
}

// Otherwise return an error indicating that the values of mixed types cannot be added.
throw new Error(`Cannot add values of incompatible types: ${typeof a} and ${typeof b}`);
}
Expand Down
8 changes: 4 additions & 4 deletions test/functions/functions-binary-ops.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,11 @@ describe('Binary Operators TypeScript Test', function () {
const parser = new Parser();
assert.deepStrictEqual(parser.evaluate('null + null'), {});
});
it('should convert numeric values to numbers before adding', function () {
it('should throw error for boolean operands', function () {
const parser = new Parser();
assert.strictEqual(parser.evaluate('true + 1'), 2);
assert.strictEqual(parser.evaluate('false + 5'), 5);
assert.strictEqual(parser.evaluate('1 + true'), 2);
assert.throws(() => parser.evaluate('true + 1'), /Cannot add values of incompatible types/);
assert.throws(() => parser.evaluate('false + 5'), /Cannot add values of incompatible types/);
assert.throws(() => parser.evaluate('1 + true'), /Cannot add values of incompatible types/);
});
it('should throw error for incompatible types', function () {
const parser = new Parser();
Expand Down
Loading