Skip to content

Commit 0d88b8e

Browse files
Allow the + operator to work with more types. Throw error on incomptible types (#18)
* Allow the + operator to work with more types. * Throw error on incompatible types
1 parent 9c77348 commit 0d88b8e

2 files changed

Lines changed: 77 additions & 4 deletions

File tree

src/operators/binary/arithmetic.ts

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,45 @@ export function add(a: any, b: any): any {
88
if (a === undefined || b === undefined) {
99
return undefined;
1010
}
11-
// If both values are strings and at least one of them in a non-number
11+
12+
// If both values are numbers then we want to add the numbers.
13+
if (typeof a === 'number' && typeof b === 'number') {
14+
return a + b;
15+
}
16+
17+
// If both values are strings and at least one of them is a non-number
1218
// then we want to concatenate the strings.
1319
if (typeof a === 'string' && typeof b === 'string') {
1420
const numA = Number(a);
1521
const numB = Number(b);
22+
1623
if (isNaN(numA) || isNaN(numB)) {
17-
return a + b;
24+
return `${a}${b}`;
1825
}
1926
}
2027

21-
// Add the numeric values.
22-
return Number(a) + Number(b);
28+
// If both values are arrays then we want to concatenate the arrays.
29+
if (Array.isArray(a) && Array.isArray(b)) {
30+
return a.concat(b);
31+
}
32+
33+
// If both values are objects then we want to merge the objects.
34+
if (
35+
typeof a === 'object' &&
36+
typeof b === 'object' &&
37+
!Array.isArray(a) &&
38+
!Array.isArray(b)
39+
) {
40+
return { ...a, ...b };
41+
}
42+
43+
// If both values can be converted to numbers then we want to add the numbers.
44+
if (!isNaN(Number(a)) && !isNaN(Number(b))) {
45+
return Number(a) + Number(b);
46+
}
47+
48+
// Otherwise return an error indicating that the values of mixed types cannot be added.
49+
throw new Error(`Cannot add values of incompatible types: ${typeof a} and ${typeof b}`);
2350
}
2451

2552
export function sub(a: number | undefined, b: number | undefined): number | undefined {

test/functions/functions-binary-ops.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,52 @@ describe('Binary Operators TypeScript Test', function () {
1616
assert.strictEqual(parser.evaluate('2 + undefined'), undefined);
1717
assert.strictEqual(parser.evaluate('undefined + 2'), undefined);
1818
});
19+
it('should concatenate non-numeric strings', function () {
20+
const parser = new Parser();
21+
assert.strictEqual(parser.evaluate('"hello" + "world"'), 'helloworld');
22+
assert.strictEqual(parser.evaluate('"foo" + "bar"'), 'foobar');
23+
assert.strictEqual(parser.evaluate('"test" + "123"'), 'test123');
24+
});
25+
it('should add numeric strings as numbers', function () {
26+
const parser = new Parser();
27+
assert.strictEqual(parser.evaluate('"5" + "3"'), 8);
28+
assert.strictEqual(parser.evaluate('"10" + "20"'), 30);
29+
assert.strictEqual(parser.evaluate('"0" + "5"'), 5);
30+
});
31+
it('should concatenate arrays', function () {
32+
const parser = new Parser();
33+
assert.deepStrictEqual(parser.evaluate('[1, 2] + [3, 4]'), [1, 2, 3, 4]);
34+
assert.deepStrictEqual(parser.evaluate('[1] + [2, 3]'), [1, 2, 3]);
35+
assert.deepStrictEqual(parser.evaluate('[] + [1, 2]'), [1, 2]);
36+
});
37+
it('should merge objects', function () {
38+
const parser = new Parser();
39+
assert.deepStrictEqual(parser.evaluate('{a: 1} + {b: 2}'), { a: 1, b: 2 });
40+
assert.deepStrictEqual(parser.evaluate('{x: 10} + {y: 20}'), { x: 10, y: 20 });
41+
assert.deepStrictEqual(parser.evaluate('{a: 1, b: 2} + {c: 3}'), { a: 1, b: 2, c: 3 });
42+
});
43+
it('should handle object merging with overlapping keys', function () {
44+
const parser = new Parser();
45+
assert.deepStrictEqual(parser.evaluate('{a: 1} + {a: 2}'), { a: 2 });
46+
assert.deepStrictEqual(parser.evaluate('{x: 10, y: 20} + {y: 30}'), { x: 10, y: 30 });
47+
});
48+
it('should handle null values correctly', function () {
49+
const parser = new Parser();
50+
assert.deepStrictEqual(parser.evaluate('null + null'), {});
51+
});
52+
it('should convert numeric values to numbers before adding', function () {
53+
const parser = new Parser();
54+
assert.strictEqual(parser.evaluate('true + 1'), 2);
55+
assert.strictEqual(parser.evaluate('false + 5'), 5);
56+
assert.strictEqual(parser.evaluate('1 + true'), 2);
57+
});
58+
it('should throw error for incompatible types', function () {
59+
const parser = new Parser();
60+
assert.throws(() => parser.evaluate('5 + [1, 2]'), /Cannot add values of incompatible types/);
61+
assert.throws(() => parser.evaluate('"text" + {a: 1}'), /Cannot add values of incompatible types/);
62+
assert.throws(() => parser.evaluate('[1, 2] + {a: 1}'), /Cannot add values of incompatible types/);
63+
assert.throws(() => parser.evaluate('5 + {x: 1}'), /Cannot add values of incompatible types/);
64+
});
1965
});
2066

2167
describe('- (subtraction)', function () {

0 commit comments

Comments
 (0)