Skip to content

Commit 8b0c9cf

Browse files
committed
feat: 🎸 add support for subtraction
1 parent 8a27a18 commit 8b0c9cf

File tree

11 files changed

+144
-15
lines changed

11 files changed

+144
-15
lines changed

README.md

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,9 +334,38 @@ eightFeet.value === 8;
334334
eightFeet.unit === foot;
335335
```
336336

337+
#### `.subtract(measurement1, measurement2)`
338+
339+
`subtract` will take the two given measurements and attempt to subtract them, converting them if needed.
340+
341+
Consider a `UnitSystem` that defines centimeters and inches:
342+
343+
```js
344+
const centimeter = createUnit('centimeter');
345+
const inch = createUnit('inch', {
346+
alias: 'inches',
347+
convert: {
348+
to: [centimeter, conversion.multiplyBy(2.54)],
349+
},
350+
});
351+
```
352+
353+
It can subtract two values in either of those units, converting them to the same unit:
354+
355+
```js
356+
const eighteenInches = system.subtract(
357+
m`24 inches`,
358+
m(15.24, centimeter)
359+
);
360+
eighteenInches.value === 18;
361+
eighteenInches.unit === inch;
362+
```
363+
364+
`subtract` does not support operating on more than 2 measurements at a time.
365+
337366
## Roadmap
338367

339-
- Unit-safe math operations beyond `add`
368+
- Unit-safe math operations beyond `add` and `subtract`
340369
- Extended units:
341370
- Compound units - `m^2`, `m^3`
342371
- Rate units - `m/s`, `mph`

src/UnitSystem/UnitSystem.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const { add } = require('../math');
1+
const { add, subtract } = require('../math');
22
const Measurement = require('../Measurement');
33
const Unit = require('../Unit');
44
const Aliases = require('./Aliases');
@@ -98,6 +98,10 @@ class UnitSystem {
9898
const unit = measurements[0].unit;
9999
return add(...measurements.map(m => this.convert(m, unit)));
100100
}
101+
subtract(...measurements) {
102+
const unit = measurements[0].unit;
103+
return subtract(...measurements.map(m => this.convert(m, unit)));
104+
}
101105
}
102106

103107
module.exports = UnitSystem;

src/UnitSystem/UnitSystem.test.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,4 +287,28 @@ describe(UnitSystem, () => {
287287
).toEqual(new Measurement(2, foot));
288288
});
289289
});
290+
291+
describe('#subtract', () => {
292+
it('subtracts', () => {
293+
const inch = new Unit('inch');
294+
const system = new UnitSystem([[inch]]);
295+
296+
expect(
297+
system.subtract(new Measurement(3, inch), new Measurement(1, inch))
298+
).toEqual(new Measurement(2, inch));
299+
});
300+
301+
it('subtracts measurements in compatible units', () => {
302+
const inch = new Unit('inch');
303+
const foot = new Unit('foot');
304+
const system = new UnitSystem([
305+
[inch],
306+
[foot, { convert: { to: [inch, multiplyBy(12)] } }],
307+
]);
308+
309+
expect(
310+
system.subtract(new Measurement(2, foot), new Measurement(12, inch))
311+
).toEqual(new Measurement(1, foot));
312+
});
313+
});
290314
});

src/createUnitSystem.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,11 @@ function createUnitSystem(units) {
1717

1818
const convert = bound(system, 'convert');
1919
const add = bound(system, 'add');
20+
const subtract = bound(system, 'subtract');
2021

2122
const m = createMeasurement(system);
2223

23-
return { m, createUnit, convert, add, system };
24+
return { m, createUnit, convert, add, subtract, system };
2425
}
2526

2627
module.exports = createUnitSystem;

src/createUnitSystem.test.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ describe(createUnitSystem, () => {
1010
m: jasmine.any(Function),
1111
convert: jasmine.any(Function),
1212
add: jasmine.any(Function),
13+
subtract: jasmine.any(Function),
1314
});
1415
});
1516

src/index.test.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ describe('createUnitSystem', () => {
1414
const { createUnitSystem, conversion } = index;
1515

1616
test('creates a functional unit system', () => {
17-
const { createUnit, m, convert, add } = createUnitSystem();
17+
const { createUnit, m, convert, add, subtract } = createUnitSystem();
1818

1919
const kilometer = createUnit('kilometer', {
2020
alias: 'km',
@@ -53,8 +53,7 @@ describe('createUnitSystem', () => {
5353

5454
expect(
5555
add(
56-
m`2 feet`,
57-
m`12 inches`,
56+
subtract(m`4 feet`, m`12 inches`),
5857
m`2 inches`,
5958
m(15.24, centimeter),
6059
m`10 inches`,

src/math/add.js

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,6 @@
1+
const measurementsHaveSameUnit = require('./measurementsHaveSameUnit');
12
const Measurement = require('../Measurement');
23

3-
function unitsDoNotMatch(measurement, index, array) {
4-
if (index === 0) {
5-
return false;
6-
}
7-
const previousMeasurement = array[index - 1];
8-
return previousMeasurement.unit !== measurement.unit;
9-
}
10-
114
function _add(measurements) {
125
return measurements.reduce(
136
(total, measurement) => total + measurement.value,
@@ -22,7 +15,7 @@ function add(...measurements) {
2215
if (measurements.length === 1) {
2316
return measurements[0];
2417
}
25-
if (measurements.some(unitsDoNotMatch)) {
18+
if (!measurementsHaveSameUnit(measurements)) {
2619
throw new TypeError('Cannot add measurements with different units');
2720
}
2821
const unit = measurements[0].unit;

src/math/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
const add = require('./add');
2+
const subtract = require('./subtract');
23

34
exports.add = add;
5+
exports.subtract = subtract;
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
function measurementsHaveSameUnit(measurements) {
2+
return measurements.every((measurement, index, array) => {
3+
if (index === 0) {
4+
return true;
5+
}
6+
const previousMeasurement = array[index - 1];
7+
return previousMeasurement.unit === measurement.unit;
8+
});
9+
}
10+
11+
module.exports = measurementsHaveSameUnit;

src/math/subtract.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
const measurementsHaveSameUnit = require('./measurementsHaveSameUnit');
2+
const Measurement = require('../Measurement');
3+
4+
function subtract(...measurements) {
5+
if (measurements.length < 1 || measurements.length > 2) {
6+
throw new TypeError(
7+
`Expected exactly 2 Measurements but got ${measurements.length}`
8+
);
9+
}
10+
if (measurements.length === 1) {
11+
return measurements[0];
12+
}
13+
if (!measurementsHaveSameUnit(measurements)) {
14+
throw new TypeError('Cannot subtract measurements with different units');
15+
}
16+
const unit = measurements[0].unit;
17+
return new Measurement(measurements[0].value - measurements[1].value, unit);
18+
}
19+
20+
module.exports = subtract;

0 commit comments

Comments
 (0)