measurable 1.0.0 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +129 -1
- package/dist/dimensions/angle.d.ts +3 -0
- package/dist/dimensions/angle.js +5 -1
- package/dist/dimensions/force.d.ts +3 -1
- package/dist/dimensions/force.js +5 -2
- package/dist/dimensions/length.d.ts +3 -3
- package/dist/dimensions/length.js +6 -4
- package/dist/dimensions/mass.d.ts +9 -4
- package/dist/dimensions/mass.js +18 -11
- package/dist/dimensions/time.d.ts +6 -1
- package/dist/dimensions/time.js +8 -2
- package/dist/dimensions/volume.d.ts +3 -1
- package/dist/dimensions/volume.js +5 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/lib/Quantity.d.ts +88 -0
- package/dist/lib/Quantity.js +168 -0
- package/dist/lib/prefixes.d.ts +34 -0
- package/dist/lib/prefixes.js +56 -0
- package/dist/systems/metric.d.ts +1 -1
- package/dist/systems/metric.js +4 -4
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -64,12 +64,21 @@ Import any dimension or unit from `measurable/dimensions`:
|
|
|
64
64
|
| ------------- | ---------- | ----------------------------------------------------------------------------------- |
|
|
65
65
|
| `length` | `meter` | `kilometer`, `centimeter`, `millimeter`, `inch`, `foot`, `yard`, `mile` |
|
|
66
66
|
| `volume` | `liter` | `milliliter`, `us*`/`imperial*` `Gallon`/`Quart`/`Pint`/`Gill`/`FluidOunce`, `cup`, `tablespoon`, `teaspoon` |
|
|
67
|
-
| `mass` | `
|
|
67
|
+
| `mass` | `gram` | `kilogram`, `milligram`, `tonne`, `pound`, `ounce`, `stone`, `shortTon`, `longTon` |
|
|
68
68
|
| `time` | `second` | `millisecond`, `minute`, `hour`, `day`, `week` |
|
|
69
69
|
| `temperature` | `kelvin` | `celsius`, `fahrenheit` |
|
|
70
70
|
| `angle` | `radian` | `degree`, `gradian`, `turn` |
|
|
71
71
|
| `force` | `newton` | `kilonewton`, `dyne`, `poundForce`, `kilogramForce` |
|
|
72
72
|
|
|
73
|
+
The metric units carry the **full SI prefix ladder** (yotta → yocto), generated for
|
|
74
|
+
you: `length`, `mass`, `volume`, and `force` get every prefix (so `kilogram`
|
|
75
|
+
itself is just the kilo-prefixed gram), while `time` and `angle` get the
|
|
76
|
+
fractional prefixes only (e.g.
|
|
77
|
+
`millisecond`, `microradian`). So `decimeter`, `hectometer`, `megagram`,
|
|
78
|
+
`kiloliter`, `nanosecond`, etc. are all available and parse from their symbols
|
|
79
|
+
(`dm`, `hm`, `Mg`, `kL`, `ns`, and `µm`/`um` for micro). You can apply the same
|
|
80
|
+
ladder to your own dimensions with `definePrefixed` (see below).
|
|
81
|
+
|
|
73
82
|
## Built-in measurement systems
|
|
74
83
|
|
|
75
84
|
Import `metric`, `imperial`, or `usCustomary` from `measurable/systems`.
|
|
@@ -106,6 +115,10 @@ metric.express(new Quantity(5000, meter)); // Quantity(5, kilometer)
|
|
|
106
115
|
imperial.express(new Quantity(5000, meter)); // Quantity(3.107…, mile)
|
|
107
116
|
```
|
|
108
117
|
|
|
118
|
+
A `Quantity` also has a `toString()` that renders `"<magnitude> <unit name>"`
|
|
119
|
+
(e.g. `new Quantity(5, kilometer).toString()` → `"5 kilometer"`), and `round(decimals)`
|
|
120
|
+
to trim the magnitude for display (`new Quantity(1.6213, mile).round(2)` → `1.62 mile`).
|
|
121
|
+
|
|
109
122
|
## Parsing strings
|
|
110
123
|
|
|
111
124
|
`Quantity.parse(input, dimension, options?)` reads a string into a `Quantity`.
|
|
@@ -146,6 +159,92 @@ import { shortTon, tonne } from "measurable/dimensions";
|
|
|
146
159
|
new Quantity(1, shortTon).in(tonne); // 0.90718474
|
|
147
160
|
```
|
|
148
161
|
|
|
162
|
+
## Arithmetic
|
|
163
|
+
|
|
164
|
+
Quantities can be combined. `plus`/`minus` take another `Quantity` (converted into
|
|
165
|
+
the receiver's unit first, so the operands may use different units of the same
|
|
166
|
+
dimension); `times`/`dividedBy` apply a dimensionless scalar, and `negate`/`abs`
|
|
167
|
+
transform the magnitude. All return a **new** `Quantity` in the receiver's unit and
|
|
168
|
+
leave the operands untouched.
|
|
169
|
+
|
|
170
|
+
```ts
|
|
171
|
+
import { Quantity } from "measurable";
|
|
172
|
+
import { kilometer, mile } from "measurable/dimensions";
|
|
173
|
+
|
|
174
|
+
new Quantity(1, mile).plus(new Quantity(1, kilometer)); // Quantity(1.6213…, mile)
|
|
175
|
+
new Quantity(1, mile).minus(new Quantity(1, kilometer)); // Quantity(0.3786…, mile)
|
|
176
|
+
new Quantity(2, mile).times(3); // Quantity(6, mile)
|
|
177
|
+
new Quantity(6, mile).dividedBy(2); // Quantity(3, mile)
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Short aliases are available: **`add`** (`plus`), **`sub`** (`minus`), **`mul`**
|
|
181
|
+
(`times`), **`div`** (`dividedBy`).
|
|
182
|
+
|
|
183
|
+
Combining different dimensions throws `InvalidConversionError`. Note that adding
|
|
184
|
+
**affine** units (e.g. temperatures) is mathematically defined but physically
|
|
185
|
+
questionable, since it adds absolute points rather than a difference.
|
|
186
|
+
|
|
187
|
+
## Ratios
|
|
188
|
+
|
|
189
|
+
`ratioTo` divides two quantities of the **same dimension** and returns a plain
|
|
190
|
+
(dimensionless) number — _how many of one fit in the other_:
|
|
191
|
+
|
|
192
|
+
```ts
|
|
193
|
+
import { Quantity } from "measurable";
|
|
194
|
+
import { liter, milliliter } from "measurable/dimensions";
|
|
195
|
+
|
|
196
|
+
// How many 250 mL servings are in a 2 L bottle?
|
|
197
|
+
new Quantity(2, liter).ratioTo(new Quantity(250, milliliter)); // 8
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
This is different from `.in(unit)`: `.in(milliliter)` only uses the *unit* on the
|
|
201
|
+
right (giving `2000`), whereas `ratioTo` also uses the other quantity's
|
|
202
|
+
**magnitude** (the `250`), so it answers "how many of *that quantity* fit in this
|
|
203
|
+
one." It's the inverse of scalar `times` — `b.times(a.ratioTo(b))` reconstructs
|
|
204
|
+
`a`. Comparing different dimensions throws `InvalidConversionError`.
|
|
205
|
+
|
|
206
|
+
## Comparison
|
|
207
|
+
|
|
208
|
+
`equals`/`notEquals`/`lessThan`/`greaterThan`/`lessThanOrEqual`/`greaterThanOrEqual`
|
|
209
|
+
compare two quantities (the other is converted into the receiver's unit first),
|
|
210
|
+
returning a boolean. Comparing different dimensions throws `InvalidConversionError`.
|
|
211
|
+
|
|
212
|
+
```ts
|
|
213
|
+
import { Quantity } from "measurable";
|
|
214
|
+
import { kilometer, meter } from "measurable/dimensions";
|
|
215
|
+
|
|
216
|
+
new Quantity(1, kilometer).equals(new Quantity(1000, meter)); // true
|
|
217
|
+
new Quantity(1, meter).lessThan(new Quantity(1, kilometer)); // true
|
|
218
|
+
new Quantity(1, kilometer).greaterThan(new Quantity(1, meter)); // true
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
Short aliases: **`eq`** (`equals`), **`ne`** (`notEquals`), **`lt`** (`lessThan`),
|
|
222
|
+
**`gt`** (`greaterThan`), **`lte`** (`lessThanOrEqual`), **`gte`**
|
|
223
|
+
(`greaterThanOrEqual`). Equality is exact, so values differing only by
|
|
224
|
+
floating-point rounding from a conversion may compare unequal.
|
|
225
|
+
|
|
226
|
+
`compareTo(other)` returns `-1`, `0`, or `1`, suitable as an `Array#sort`
|
|
227
|
+
comparator: `quantities.sort((a, b) => a.compareTo(b))`.
|
|
228
|
+
|
|
229
|
+
## Combining quantities
|
|
230
|
+
|
|
231
|
+
`Quantity.min`/`max`/`sum` aggregate several quantities at once; `clamp` is an
|
|
232
|
+
instance method that bounds one quantity to a range. Each converts operands as
|
|
233
|
+
needed, so mixing dimensions throws `InvalidConversionError`.
|
|
234
|
+
|
|
235
|
+
```ts
|
|
236
|
+
import { Quantity } from "measurable";
|
|
237
|
+
import { kilometer, meter } from "measurable/dimensions";
|
|
238
|
+
|
|
239
|
+
const a = new Quantity(1, kilometer);
|
|
240
|
+
const b = new Quantity(500, meter);
|
|
241
|
+
|
|
242
|
+
Quantity.min(a, b); // Quantity(500, meter) — the smaller
|
|
243
|
+
Quantity.max(a, b); // Quantity(1, kilometer) — the larger
|
|
244
|
+
Quantity.sum(a, b); // Quantity(1.5, kilometer) — total, in a's unit
|
|
245
|
+
b.clamp(a, new Quantity(2, kilometer)); // b bounded to [a, 2 km], in b's unit
|
|
246
|
+
```
|
|
247
|
+
|
|
149
248
|
## Defining your own units
|
|
150
249
|
|
|
151
250
|
Create a `Dimension` and add units through its builder methods. `scale` is how
|
|
@@ -184,6 +283,22 @@ dim.custom("squared", {
|
|
|
184
283
|
});
|
|
185
284
|
```
|
|
186
285
|
|
|
286
|
+
### Generating SI prefixes
|
|
287
|
+
|
|
288
|
+
`definePrefixed` adds the metric prefix ladder to a reference unit and returns the
|
|
289
|
+
created units keyed by name (skipping any name that already exists). Pass
|
|
290
|
+
`SI_SUBMULTIPLE_PREFIXES` to generate fractions only.
|
|
291
|
+
|
|
292
|
+
```ts
|
|
293
|
+
import { Dimension, Quantity, definePrefixed } from "measurable";
|
|
294
|
+
|
|
295
|
+
const data = new Dimension("data");
|
|
296
|
+
const bit = data.base("bit", ["b"]);
|
|
297
|
+
const prefixed = definePrefixed(data, { name: "bit", symbol: "b", scale: 1 });
|
|
298
|
+
|
|
299
|
+
new Quantity(1, prefixed.kilobit).in(bit); // 1000 (SI kilo = 1e3)
|
|
300
|
+
```
|
|
301
|
+
|
|
187
302
|
### Tagging units into a measurement system
|
|
188
303
|
|
|
189
304
|
```ts
|
|
@@ -221,6 +336,19 @@ A passive handle, normally created via a dimension's builder methods rather than
|
|
|
221
336
|
- `new Quantity(magnitude, unit)`
|
|
222
337
|
- `.to(target)` → `Quantity`
|
|
223
338
|
- `.in(target)` → `number`
|
|
339
|
+
- `.toString()` → `string` — e.g. `"5 kilometer"`
|
|
340
|
+
- `.plus(other)` / `.minus(other)` → `Quantity` — add/subtract another quantity (aliases: `add` / `sub`)
|
|
341
|
+
- `.times(factor)` / `.dividedBy(divisor)` → `Quantity` — scale by a number (aliases: `mul` / `div`)
|
|
342
|
+
- `.ratioTo(other)` → `number` — dimensionless ratio (how many of `other` fit in this)
|
|
343
|
+
- `.negate()` / `.abs()` → `Quantity`
|
|
344
|
+
- `.clamp(lower, upper)` → `Quantity` — bound to a range, in this unit
|
|
345
|
+
- `.round(decimals?)` → `Quantity` — round the magnitude (default 0 decimals)
|
|
346
|
+
- `.equals(other)` / `.notEquals(other)` → `boolean` (aliases: `eq` / `ne`)
|
|
347
|
+
- `.lessThan(other)` / `.greaterThan(other)` → `boolean` (aliases: `lt` / `gt`)
|
|
348
|
+
- `.lessThanOrEqual(other)` / `.greaterThanOrEqual(other)` → `boolean` (aliases: `lte` / `gte`)
|
|
349
|
+
- `.compareTo(other)` → `-1 | 0 | 1` — sort comparator
|
|
350
|
+
- `.isZero()` / `.isPositive()` / `.isNegative()` → `boolean`
|
|
351
|
+
- `Quantity.min(...quantities)` / `Quantity.max(...quantities)` / `Quantity.sum(...quantities)` → `Quantity`
|
|
224
352
|
- `Quantity.parse(input, dimension, { prefer? })` → `Quantity`
|
|
225
353
|
|
|
226
354
|
### `MeasurementSystem`
|
|
@@ -5,3 +5,6 @@ export declare const radian: import("..").Unit;
|
|
|
5
5
|
export declare const degree: import("..").Unit;
|
|
6
6
|
export declare const gradian: import("..").Unit;
|
|
7
7
|
export declare const turn: import("..").Unit;
|
|
8
|
+
/** SI-submultiple radians (milliradian, microradian, …); larger angles use degree/turn. */
|
|
9
|
+
export declare const metricAngle: Record<string, import("..").Unit>;
|
|
10
|
+
export declare const milliradian: import("..").Unit, microradian: import("..").Unit;
|
package/dist/dimensions/angle.js
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.turn = exports.gradian = exports.degree = exports.radian = exports.angle = void 0;
|
|
3
|
+
exports.microradian = exports.milliradian = exports.metricAngle = exports.turn = exports.gradian = exports.degree = exports.radian = exports.angle = void 0;
|
|
4
4
|
const Dimension_1 = require("../lib/Dimension");
|
|
5
|
+
const prefixes_1 = require("../lib/prefixes");
|
|
5
6
|
/** Plane angle. Base unit: radian. */
|
|
6
7
|
exports.angle = new Dimension_1.Dimension("angle");
|
|
7
8
|
exports.radian = exports.angle.base("radian", ["rad", "radians"]);
|
|
8
9
|
exports.degree = exports.angle.unit("degree", Math.PI / 180, ["deg", "°", "degrees"]);
|
|
9
10
|
exports.gradian = exports.angle.unit("gradian", Math.PI / 200, ["grad", "gradians"]);
|
|
10
11
|
exports.turn = exports.angle.unit("turn", 2 * Math.PI, ["turns", "revolution", "revolutions"]);
|
|
12
|
+
/** SI-submultiple radians (milliradian, microradian, …); larger angles use degree/turn. */
|
|
13
|
+
exports.metricAngle = (0, prefixes_1.definePrefixed)(exports.angle, { name: "radian", symbol: "rad", scale: 1 }, prefixes_1.SI_SUBMULTIPLE_PREFIXES);
|
|
14
|
+
exports.milliradian = exports.metricAngle.milliradian, exports.microradian = exports.metricAngle.microradian;
|
|
@@ -2,7 +2,9 @@ import { Dimension } from "../lib/Dimension";
|
|
|
2
2
|
/** Force. Base unit: newton. */
|
|
3
3
|
export declare const force: Dimension;
|
|
4
4
|
export declare const newton: import("..").Unit;
|
|
5
|
-
export declare const kilonewton: import("..").Unit;
|
|
6
5
|
export declare const dyne: import("..").Unit;
|
|
7
6
|
export declare const poundForce: import("..").Unit;
|
|
8
7
|
export declare const kilogramForce: import("..").Unit;
|
|
8
|
+
/** Every SI-prefixed newton (kilonewton, meganewton, millinewton, …), keyed by name. */
|
|
9
|
+
export declare const metricForce: Record<string, import("..").Unit>;
|
|
10
|
+
export declare const meganewton: import("..").Unit, kilonewton: import("..").Unit, millinewton: import("..").Unit, micronewton: import("..").Unit;
|
package/dist/dimensions/force.js
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.micronewton = exports.millinewton = exports.kilonewton = exports.meganewton = exports.metricForce = exports.kilogramForce = exports.poundForce = exports.dyne = exports.newton = exports.force = void 0;
|
|
4
4
|
const Dimension_1 = require("../lib/Dimension");
|
|
5
|
+
const prefixes_1 = require("../lib/prefixes");
|
|
5
6
|
/** Force. Base unit: newton. */
|
|
6
7
|
exports.force = new Dimension_1.Dimension("force");
|
|
7
8
|
exports.newton = exports.force.base("newton", ["N", "newtons"]);
|
|
8
|
-
exports.kilonewton = exports.force.unit("kilonewton", 1000, ["kN", "kilonewtons"]);
|
|
9
9
|
exports.dyne = exports.force.unit("dyne", 0.00001, ["dyn", "dynes"]);
|
|
10
10
|
exports.poundForce = exports.force.unit("poundForce", 4.4482216152605, ["lbf"]);
|
|
11
11
|
exports.kilogramForce = exports.force.unit("kilogramForce", 9.80665, ["kgf"]);
|
|
12
|
+
/** Every SI-prefixed newton (kilonewton, meganewton, millinewton, …), keyed by name. */
|
|
13
|
+
exports.metricForce = (0, prefixes_1.definePrefixed)(exports.force, { name: "newton", symbol: "N", scale: 1 });
|
|
14
|
+
exports.meganewton = exports.metricForce.meganewton, exports.kilonewton = exports.metricForce.kilonewton, exports.millinewton = exports.metricForce.millinewton, exports.micronewton = exports.metricForce.micronewton;
|
|
@@ -2,10 +2,10 @@ import { Dimension } from "../lib/Dimension";
|
|
|
2
2
|
/** Length / distance. Base unit: meter. */
|
|
3
3
|
export declare const length: Dimension;
|
|
4
4
|
export declare const meter: import("..").Unit;
|
|
5
|
-
export declare const kilometer: import("..").Unit;
|
|
6
|
-
export declare const centimeter: import("..").Unit;
|
|
7
|
-
export declare const millimeter: import("..").Unit;
|
|
8
5
|
export declare const inch: import("..").Unit;
|
|
9
6
|
export declare const foot: import("..").Unit;
|
|
10
7
|
export declare const yard: import("..").Unit;
|
|
11
8
|
export declare const mile: import("..").Unit;
|
|
9
|
+
/** Every SI-prefixed meter (kilometer, centimeter, micrometer, …), keyed by name. */
|
|
10
|
+
export declare const metricLength: Record<string, import("..").Unit>;
|
|
11
|
+
export declare const kilometer: import("..").Unit, hectometer: import("..").Unit, decameter: import("..").Unit, decimeter: import("..").Unit, centimeter: import("..").Unit, millimeter: import("..").Unit, micrometer: import("..").Unit, nanometer: import("..").Unit;
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.nanometer = exports.micrometer = exports.millimeter = exports.centimeter = exports.decimeter = exports.decameter = exports.hectometer = exports.kilometer = exports.metricLength = exports.mile = exports.yard = exports.foot = exports.inch = exports.meter = exports.length = void 0;
|
|
4
4
|
const Dimension_1 = require("../lib/Dimension");
|
|
5
|
+
const prefixes_1 = require("../lib/prefixes");
|
|
5
6
|
/** Length / distance. Base unit: meter. */
|
|
6
7
|
exports.length = new Dimension_1.Dimension("length");
|
|
7
8
|
exports.meter = exports.length.base("meter", ["m", "meters"]);
|
|
8
|
-
|
|
9
|
-
exports.centimeter = exports.length.unit("centimeter", 0.01, ["cm", "centimeters"]);
|
|
10
|
-
exports.millimeter = exports.length.unit("millimeter", 0.001, ["mm", "millimeters"]);
|
|
9
|
+
// Imperial / US customary.
|
|
11
10
|
exports.inch = exports.length.unit("inch", 0.0254, ["in", "inches"]);
|
|
12
11
|
exports.foot = exports.length.unit("foot", 0.3048, ["ft", "feet"]);
|
|
13
12
|
exports.yard = exports.length.unit("yard", 0.9144, ["yd", "yards"]);
|
|
14
13
|
exports.mile = exports.length.unit("mile", 1609.344, ["mi", "miles"]);
|
|
14
|
+
/** Every SI-prefixed meter (kilometer, centimeter, micrometer, …), keyed by name. */
|
|
15
|
+
exports.metricLength = (0, prefixes_1.definePrefixed)(exports.length, { name: "meter", symbol: "m", scale: 1 });
|
|
16
|
+
exports.kilometer = exports.metricLength.kilometer, exports.hectometer = exports.metricLength.hectometer, exports.decameter = exports.metricLength.decameter, exports.decimeter = exports.metricLength.decimeter, exports.centimeter = exports.metricLength.centimeter, exports.millimeter = exports.metricLength.millimeter, exports.micrometer = exports.metricLength.micrometer, exports.nanometer = exports.metricLength.nanometer;
|
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
import { Dimension } from "../lib/Dimension";
|
|
2
|
-
/**
|
|
2
|
+
/**
|
|
3
|
+
* Mass / weight. Base unit: gram. (SI's official base is the kilogram, but
|
|
4
|
+
* prefixes attach to the gram, so gram is the natural routing anchor — the
|
|
5
|
+
* choice of base is internal and does not affect any conversion.)
|
|
6
|
+
*/
|
|
3
7
|
export declare const mass: Dimension;
|
|
4
|
-
export declare const kilogram: import("..").Unit;
|
|
5
8
|
export declare const gram: import("..").Unit;
|
|
6
|
-
export declare const milligram: import("..").Unit;
|
|
7
|
-
export declare const tonne: import("..").Unit;
|
|
8
9
|
export declare const pound: import("..").Unit;
|
|
9
10
|
export declare const ounce: import("..").Unit;
|
|
10
11
|
export declare const stone: import("..").Unit;
|
|
12
|
+
export declare const tonne: import("..").Unit;
|
|
11
13
|
export declare const shortTon: import("..").Unit;
|
|
12
14
|
export declare const longTon: import("..").Unit;
|
|
15
|
+
/** Every SI-prefixed gram — including the kilogram — keyed by name. */
|
|
16
|
+
export declare const metricMass: Record<string, import("..").Unit>;
|
|
17
|
+
export declare const kilogram: import("..").Unit, megagram: import("..").Unit, hectogram: import("..").Unit, decagram: import("..").Unit, decigram: import("..").Unit, centigram: import("..").Unit, milligram: import("..").Unit, microgram: import("..").Unit, nanogram: import("..").Unit;
|
package/dist/dimensions/mass.js
CHANGED
|
@@ -1,17 +1,24 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.nanogram = exports.microgram = exports.milligram = exports.centigram = exports.decigram = exports.decagram = exports.hectogram = exports.megagram = exports.kilogram = exports.metricMass = exports.longTon = exports.shortTon = exports.tonne = exports.stone = exports.ounce = exports.pound = exports.gram = exports.mass = void 0;
|
|
4
4
|
const Dimension_1 = require("../lib/Dimension");
|
|
5
|
-
|
|
5
|
+
const prefixes_1 = require("../lib/prefixes");
|
|
6
|
+
/**
|
|
7
|
+
* Mass / weight. Base unit: gram. (SI's official base is the kilogram, but
|
|
8
|
+
* prefixes attach to the gram, so gram is the natural routing anchor — the
|
|
9
|
+
* choice of base is internal and does not affect any conversion.)
|
|
10
|
+
*/
|
|
6
11
|
exports.mass = new Dimension_1.Dimension("mass");
|
|
7
|
-
exports.
|
|
8
|
-
|
|
9
|
-
exports.
|
|
10
|
-
exports.
|
|
11
|
-
exports.
|
|
12
|
-
exports.
|
|
13
|
-
exports.stone = exports.mass.unit("stone", 6.35029318, ["st", "stones"]);
|
|
12
|
+
exports.gram = exports.mass.base("gram", ["g", "grams"]);
|
|
13
|
+
// Customary units, expressed in grams.
|
|
14
|
+
exports.pound = exports.mass.unit("pound", 453.59237, ["lb", "lbs", "pounds"]);
|
|
15
|
+
exports.ounce = exports.mass.unit("ounce", 28.349523125, ["oz", "ounces"]);
|
|
16
|
+
exports.stone = exports.mass.unit("stone", 6350.29318, ["st", "stones"]);
|
|
17
|
+
exports.tonne = exports.mass.unit("tonne", 1000000, ["t", "tonnes"]);
|
|
14
18
|
// Short (US) and long (Imperial) tons share the "ton" alias but differ in size;
|
|
15
19
|
// the metric tonne above is a separate unit again. Parsing disambiguates these.
|
|
16
|
-
exports.shortTon = exports.mass.unit("shortTon",
|
|
17
|
-
exports.longTon = exports.mass.unit("longTon",
|
|
20
|
+
exports.shortTon = exports.mass.unit("shortTon", 907184.74, ["ton", "tons"]);
|
|
21
|
+
exports.longTon = exports.mass.unit("longTon", 1016046.9088, ["ton", "tons"]);
|
|
22
|
+
/** Every SI-prefixed gram — including the kilogram — keyed by name. */
|
|
23
|
+
exports.metricMass = (0, prefixes_1.definePrefixed)(exports.mass, { name: "gram", symbol: "g", scale: 1 });
|
|
24
|
+
exports.kilogram = exports.metricMass.kilogram, exports.megagram = exports.metricMass.megagram, exports.hectogram = exports.metricMass.hectogram, exports.decagram = exports.metricMass.decagram, exports.decigram = exports.metricMass.decigram, exports.centigram = exports.metricMass.centigram, exports.milligram = exports.metricMass.milligram, exports.microgram = exports.metricMass.microgram, exports.nanogram = exports.metricMass.nanogram;
|
|
@@ -2,8 +2,13 @@ import { Dimension } from "../lib/Dimension";
|
|
|
2
2
|
/** Time / duration. Base unit: second. */
|
|
3
3
|
export declare const time: Dimension;
|
|
4
4
|
export declare const second: import("..").Unit;
|
|
5
|
-
export declare const millisecond: import("..").Unit;
|
|
6
5
|
export declare const minute: import("..").Unit;
|
|
7
6
|
export declare const hour: import("..").Unit;
|
|
8
7
|
export declare const day: import("..").Unit;
|
|
9
8
|
export declare const week: import("..").Unit;
|
|
9
|
+
/**
|
|
10
|
+
* SI-submultiple seconds (millisecond, microsecond, nanosecond, …). Only
|
|
11
|
+
* fractions are generated; larger spans use minute/hour/day/week above.
|
|
12
|
+
*/
|
|
13
|
+
export declare const metricTime: Record<string, import("..").Unit>;
|
|
14
|
+
export declare const millisecond: import("..").Unit, microsecond: import("..").Unit, nanosecond: import("..").Unit, picosecond: import("..").Unit;
|
package/dist/dimensions/time.js
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.picosecond = exports.nanosecond = exports.microsecond = exports.millisecond = exports.metricTime = exports.week = exports.day = exports.hour = exports.minute = exports.second = exports.time = void 0;
|
|
4
4
|
const Dimension_1 = require("../lib/Dimension");
|
|
5
|
+
const prefixes_1 = require("../lib/prefixes");
|
|
5
6
|
/** Time / duration. Base unit: second. */
|
|
6
7
|
exports.time = new Dimension_1.Dimension("time");
|
|
7
8
|
exports.second = exports.time.base("second", ["s", "sec", "secs", "seconds"]);
|
|
8
|
-
exports.millisecond = exports.time.unit("millisecond", 0.001, ["ms", "milliseconds"]);
|
|
9
9
|
exports.minute = exports.time.unit("minute", 60, ["min", "mins", "minutes"]);
|
|
10
10
|
exports.hour = exports.time.unit("hour", 3600, ["h", "hr", "hrs", "hours"]);
|
|
11
11
|
exports.day = exports.time.unit("day", 86400, ["d", "days"]);
|
|
12
12
|
exports.week = exports.time.unit("week", 604800, ["wk", "weeks"]);
|
|
13
|
+
/**
|
|
14
|
+
* SI-submultiple seconds (millisecond, microsecond, nanosecond, …). Only
|
|
15
|
+
* fractions are generated; larger spans use minute/hour/day/week above.
|
|
16
|
+
*/
|
|
17
|
+
exports.metricTime = (0, prefixes_1.definePrefixed)(exports.time, { name: "second", symbol: "s", scale: 1 }, prefixes_1.SI_SUBMULTIPLE_PREFIXES);
|
|
18
|
+
exports.millisecond = exports.metricTime.millisecond, exports.microsecond = exports.metricTime.microsecond, exports.nanosecond = exports.metricTime.nanosecond, exports.picosecond = exports.metricTime.picosecond;
|
|
@@ -2,7 +2,6 @@ import { Dimension } from "../lib/Dimension";
|
|
|
2
2
|
/** Volume / capacity. Base unit: liter. */
|
|
3
3
|
export declare const volume: Dimension;
|
|
4
4
|
export declare const liter: import("..").Unit;
|
|
5
|
-
export declare const milliliter: import("..").Unit;
|
|
6
5
|
export declare const usGallon: import("..").Unit;
|
|
7
6
|
export declare const usQuart: import("..").Unit;
|
|
8
7
|
export declare const usPint: import("..").Unit;
|
|
@@ -16,3 +15,6 @@ export declare const imperialFluidOunce: import("..").Unit;
|
|
|
16
15
|
export declare const cup: import("..").Unit;
|
|
17
16
|
export declare const tablespoon: import("..").Unit;
|
|
18
17
|
export declare const teaspoon: import("..").Unit;
|
|
18
|
+
/** Every SI-prefixed liter (milliliter, centiliter, kiloliter, …), keyed by name. */
|
|
19
|
+
export declare const metricVolume: Record<string, import("..").Unit>;
|
|
20
|
+
export declare const kiloliter: import("..").Unit, hectoliter: import("..").Unit, decaliter: import("..").Unit, deciliter: import("..").Unit, centiliter: import("..").Unit, milliliter: import("..").Unit;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.teaspoon = exports.tablespoon = exports.cup = exports.imperialFluidOunce = exports.imperialGill = exports.imperialPint = exports.imperialQuart = exports.imperialGallon = exports.usFluidOunce = exports.usGill = exports.usPint = exports.usQuart = exports.usGallon = exports.
|
|
3
|
+
exports.milliliter = exports.centiliter = exports.deciliter = exports.decaliter = exports.hectoliter = exports.kiloliter = exports.metricVolume = exports.teaspoon = exports.tablespoon = exports.cup = exports.imperialFluidOunce = exports.imperialGill = exports.imperialPint = exports.imperialQuart = exports.imperialGallon = exports.usFluidOunce = exports.usGill = exports.usPint = exports.usQuart = exports.usGallon = exports.liter = exports.volume = void 0;
|
|
4
4
|
const Dimension_1 = require("../lib/Dimension");
|
|
5
|
+
const prefixes_1 = require("../lib/prefixes");
|
|
5
6
|
/** Volume / capacity. Base unit: liter. */
|
|
6
7
|
exports.volume = new Dimension_1.Dimension("volume");
|
|
7
8
|
exports.liter = exports.volume.base("liter", ["L", "liters"]);
|
|
8
|
-
exports.milliliter = exports.volume.unit("milliliter", 0.001, ["mL", "milliliters"]);
|
|
9
9
|
// US and Imperial liquid measures share names ("gallon", "pint", …) but differ
|
|
10
10
|
// in size, so each is a distinct unit carrying the shared aliases; parsing
|
|
11
11
|
// disambiguates via a preferred measurement system. Imperial has 160 fluid
|
|
@@ -32,3 +32,6 @@ exports.imperialFluidOunce = exports.volume.unit("imperialFluidOunce", 0.0284130
|
|
|
32
32
|
exports.cup = exports.volume.unit("cup", 0.2365882365, ["cups"]);
|
|
33
33
|
exports.tablespoon = exports.volume.unit("tablespoon", 0.01478676478125, ["tbsp", "tablespoons"]);
|
|
34
34
|
exports.teaspoon = exports.volume.unit("teaspoon", 0.00492892159375, ["tsp", "teaspoons"]);
|
|
35
|
+
/** Every SI-prefixed liter (milliliter, centiliter, kiloliter, …), keyed by name. */
|
|
36
|
+
exports.metricVolume = (0, prefixes_1.definePrefixed)(exports.volume, { name: "liter", symbol: "L", scale: 1 });
|
|
37
|
+
exports.kiloliter = exports.metricVolume.kiloliter, exports.hectoliter = exports.metricVolume.hectoliter, exports.decaliter = exports.metricVolume.decaliter, exports.deciliter = exports.metricVolume.deciliter, exports.centiliter = exports.metricVolume.centiliter, exports.milliliter = exports.metricVolume.milliliter;
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -19,5 +19,6 @@ __exportStar(require("./errors/InvalidConversionError"), exports);
|
|
|
19
19
|
__exportStar(require("./errors/UnknownUnitError"), exports);
|
|
20
20
|
__exportStar(require("./lib/Dimension"), exports);
|
|
21
21
|
__exportStar(require("./lib/MeasurementSystem"), exports);
|
|
22
|
+
__exportStar(require("./lib/prefixes"), exports);
|
|
22
23
|
__exportStar(require("./lib/Quantity"), exports);
|
|
23
24
|
__exportStar(require("./lib/Unit"), exports);
|
package/dist/lib/Quantity.d.ts
CHANGED
|
@@ -15,6 +15,88 @@ export declare class Quantity {
|
|
|
15
15
|
to(target: Unit): Quantity;
|
|
16
16
|
/** Return this quantity's raw magnitude expressed in `target`. */
|
|
17
17
|
in(target: Unit): number;
|
|
18
|
+
/** Render as `"<magnitude> <unit name>"`, e.g. `"5 kilometer"`. */
|
|
19
|
+
toString(): string;
|
|
20
|
+
/**
|
|
21
|
+
* Add another quantity, returned in *this* quantity's unit. The other operand
|
|
22
|
+
* is converted into this unit first, so the two may use different units of the
|
|
23
|
+
* same dimension (e.g. `mile.plus(km)`). Throws {@link InvalidConversionError}
|
|
24
|
+
* if the operands belong to different dimensions.
|
|
25
|
+
*
|
|
26
|
+
* Note: for affine units (e.g. temperature) addition is mathematically defined
|
|
27
|
+
* but physically questionable, since it adds absolute points rather than a
|
|
28
|
+
* difference.
|
|
29
|
+
*/
|
|
30
|
+
plus(other: Quantity): Quantity;
|
|
31
|
+
/** Subtract another quantity, returned in this quantity's unit. */
|
|
32
|
+
minus(other: Quantity): Quantity;
|
|
33
|
+
/** Scale this quantity by a dimensionless factor. */
|
|
34
|
+
times(factor: number): Quantity;
|
|
35
|
+
/** Divide this quantity by a dimensionless divisor. */
|
|
36
|
+
dividedBy(divisor: number): Quantity;
|
|
37
|
+
/**
|
|
38
|
+
* Divide this quantity by `other` of the same dimension, yielding the
|
|
39
|
+
* dimensionless ratio between them — i.e. how many of `other` fit in this.
|
|
40
|
+
* Unlike {@link in}, this accounts for `other`'s magnitude, not just its unit.
|
|
41
|
+
* Throws {@link InvalidConversionError} across dimensions.
|
|
42
|
+
*/
|
|
43
|
+
ratioTo(other: Quantity): number;
|
|
44
|
+
/** Return this quantity with its magnitude negated. */
|
|
45
|
+
negate(): Quantity;
|
|
46
|
+
/** Return this quantity with a non-negative magnitude. */
|
|
47
|
+
abs(): Quantity;
|
|
48
|
+
/** Clamp this quantity to the range [`lower`, `upper`], returned in this unit. */
|
|
49
|
+
clamp(lower: Quantity, upper: Quantity): Quantity;
|
|
50
|
+
/** Return this quantity with its magnitude rounded to `decimals` places (default 0). */
|
|
51
|
+
round(decimals?: number): Quantity;
|
|
52
|
+
/** Alias for {@link plus}. */
|
|
53
|
+
add(other: Quantity): Quantity;
|
|
54
|
+
/** Alias for {@link minus}. */
|
|
55
|
+
sub(other: Quantity): Quantity;
|
|
56
|
+
/** Alias for {@link times}. */
|
|
57
|
+
mul(factor: number): Quantity;
|
|
58
|
+
/** Alias for {@link dividedBy}. */
|
|
59
|
+
div(divisor: number): Quantity;
|
|
60
|
+
/**
|
|
61
|
+
* Whether this quantity equals `other`, compared in this quantity's unit.
|
|
62
|
+
* Throws {@link InvalidConversionError} if the operands belong to different
|
|
63
|
+
* dimensions. Comparison is exact, so values that differ only by
|
|
64
|
+
* floating-point rounding from a conversion may compare unequal.
|
|
65
|
+
*/
|
|
66
|
+
equals(other: Quantity): boolean;
|
|
67
|
+
/** Whether this quantity does not equal `other`. */
|
|
68
|
+
notEquals(other: Quantity): boolean;
|
|
69
|
+
/** Whether this quantity is less than `other`. */
|
|
70
|
+
lessThan(other: Quantity): boolean;
|
|
71
|
+
/** Whether this quantity is greater than `other`. */
|
|
72
|
+
greaterThan(other: Quantity): boolean;
|
|
73
|
+
/** Whether this quantity is less than or equal to `other`. */
|
|
74
|
+
lessThanOrEqual(other: Quantity): boolean;
|
|
75
|
+
/** Whether this quantity is greater than or equal to `other`. */
|
|
76
|
+
greaterThanOrEqual(other: Quantity): boolean;
|
|
77
|
+
/** Alias for {@link equals}. */
|
|
78
|
+
eq(other: Quantity): boolean;
|
|
79
|
+
/** Alias for {@link notEquals}. */
|
|
80
|
+
ne(other: Quantity): boolean;
|
|
81
|
+
/** Alias for {@link lessThan}. */
|
|
82
|
+
lt(other: Quantity): boolean;
|
|
83
|
+
/** Alias for {@link greaterThan}. */
|
|
84
|
+
gt(other: Quantity): boolean;
|
|
85
|
+
/** Alias for {@link lessThanOrEqual}. */
|
|
86
|
+
lte(other: Quantity): boolean;
|
|
87
|
+
/** Alias for {@link greaterThanOrEqual}. */
|
|
88
|
+
gte(other: Quantity): boolean;
|
|
89
|
+
/**
|
|
90
|
+
* Compare with `other` (in this quantity's unit): `-1` if this is smaller, `1`
|
|
91
|
+
* if larger, `0` if equal. Suitable as an `Array#sort` comparator.
|
|
92
|
+
*/
|
|
93
|
+
compareTo(other: Quantity): number;
|
|
94
|
+
/** Whether this quantity's magnitude is exactly zero. */
|
|
95
|
+
isZero(): boolean;
|
|
96
|
+
/** Whether this quantity's magnitude is greater than zero. */
|
|
97
|
+
isPositive(): boolean;
|
|
98
|
+
/** Whether this quantity's magnitude is less than zero. */
|
|
99
|
+
isNegative(): boolean;
|
|
18
100
|
/**
|
|
19
101
|
* Parse a string into a `Quantity` using a dimension's known units and aliases.
|
|
20
102
|
*
|
|
@@ -29,4 +111,10 @@ export declare class Quantity {
|
|
|
29
111
|
* `options.prefer` to pick the candidate belonging to that measurement system.
|
|
30
112
|
*/
|
|
31
113
|
static parse(str: string, dimension: Dimension, options?: ParseOptions): Quantity;
|
|
114
|
+
/** The smallest of the given quantities (by value); requires at least one. */
|
|
115
|
+
static min(first: Quantity, ...rest: Quantity[]): Quantity;
|
|
116
|
+
/** The largest of the given quantities (by value); requires at least one. */
|
|
117
|
+
static max(first: Quantity, ...rest: Quantity[]): Quantity;
|
|
118
|
+
/** The sum of the given quantities, in the first one's unit; requires at least one. */
|
|
119
|
+
static sum(first: Quantity, ...rest: Quantity[]): Quantity;
|
|
32
120
|
}
|
package/dist/lib/Quantity.js
CHANGED
|
@@ -18,6 +18,162 @@ class Quantity {
|
|
|
18
18
|
in(target) {
|
|
19
19
|
return this.unit.dimension.convert(this.magnitude, this.unit, target);
|
|
20
20
|
}
|
|
21
|
+
/** Render as `"<magnitude> <unit name>"`, e.g. `"5 kilometer"`. */
|
|
22
|
+
toString() {
|
|
23
|
+
return `${this.magnitude} ${this.unit.name}`;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Add another quantity, returned in *this* quantity's unit. The other operand
|
|
27
|
+
* is converted into this unit first, so the two may use different units of the
|
|
28
|
+
* same dimension (e.g. `mile.plus(km)`). Throws {@link InvalidConversionError}
|
|
29
|
+
* if the operands belong to different dimensions.
|
|
30
|
+
*
|
|
31
|
+
* Note: for affine units (e.g. temperature) addition is mathematically defined
|
|
32
|
+
* but physically questionable, since it adds absolute points rather than a
|
|
33
|
+
* difference.
|
|
34
|
+
*/
|
|
35
|
+
plus(other) {
|
|
36
|
+
return new Quantity(this.magnitude + other.in(this.unit), this.unit);
|
|
37
|
+
}
|
|
38
|
+
/** Subtract another quantity, returned in this quantity's unit. */
|
|
39
|
+
minus(other) {
|
|
40
|
+
return new Quantity(this.magnitude - other.in(this.unit), this.unit);
|
|
41
|
+
}
|
|
42
|
+
/** Scale this quantity by a dimensionless factor. */
|
|
43
|
+
times(factor) {
|
|
44
|
+
return new Quantity(this.magnitude * factor, this.unit);
|
|
45
|
+
}
|
|
46
|
+
/** Divide this quantity by a dimensionless divisor. */
|
|
47
|
+
dividedBy(divisor) {
|
|
48
|
+
return new Quantity(this.magnitude / divisor, this.unit);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Divide this quantity by `other` of the same dimension, yielding the
|
|
52
|
+
* dimensionless ratio between them — i.e. how many of `other` fit in this.
|
|
53
|
+
* Unlike {@link in}, this accounts for `other`'s magnitude, not just its unit.
|
|
54
|
+
* Throws {@link InvalidConversionError} across dimensions.
|
|
55
|
+
*/
|
|
56
|
+
ratioTo(other) {
|
|
57
|
+
return this.magnitude / other.in(this.unit);
|
|
58
|
+
}
|
|
59
|
+
/** Return this quantity with its magnitude negated. */
|
|
60
|
+
negate() {
|
|
61
|
+
return new Quantity(-this.magnitude, this.unit);
|
|
62
|
+
}
|
|
63
|
+
/** Return this quantity with a non-negative magnitude. */
|
|
64
|
+
abs() {
|
|
65
|
+
return new Quantity(Math.abs(this.magnitude), this.unit);
|
|
66
|
+
}
|
|
67
|
+
/** Clamp this quantity to the range [`lower`, `upper`], returned in this unit. */
|
|
68
|
+
clamp(lower, upper) {
|
|
69
|
+
if (this.lessThan(lower)) {
|
|
70
|
+
return lower.to(this.unit);
|
|
71
|
+
}
|
|
72
|
+
if (this.greaterThan(upper)) {
|
|
73
|
+
return upper.to(this.unit);
|
|
74
|
+
}
|
|
75
|
+
return this;
|
|
76
|
+
}
|
|
77
|
+
/** Return this quantity with its magnitude rounded to `decimals` places (default 0). */
|
|
78
|
+
round(decimals = 0) {
|
|
79
|
+
const factor = 10 ** decimals;
|
|
80
|
+
return new Quantity(Math.round(this.magnitude * factor) / factor, this.unit);
|
|
81
|
+
}
|
|
82
|
+
/** Alias for {@link plus}. */
|
|
83
|
+
add(other) {
|
|
84
|
+
return this.plus(other);
|
|
85
|
+
}
|
|
86
|
+
/** Alias for {@link minus}. */
|
|
87
|
+
sub(other) {
|
|
88
|
+
return this.minus(other);
|
|
89
|
+
}
|
|
90
|
+
/** Alias for {@link times}. */
|
|
91
|
+
mul(factor) {
|
|
92
|
+
return this.times(factor);
|
|
93
|
+
}
|
|
94
|
+
/** Alias for {@link dividedBy}. */
|
|
95
|
+
div(divisor) {
|
|
96
|
+
return this.dividedBy(divisor);
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Whether this quantity equals `other`, compared in this quantity's unit.
|
|
100
|
+
* Throws {@link InvalidConversionError} if the operands belong to different
|
|
101
|
+
* dimensions. Comparison is exact, so values that differ only by
|
|
102
|
+
* floating-point rounding from a conversion may compare unequal.
|
|
103
|
+
*/
|
|
104
|
+
equals(other) {
|
|
105
|
+
return this.magnitude === other.in(this.unit);
|
|
106
|
+
}
|
|
107
|
+
/** Whether this quantity does not equal `other`. */
|
|
108
|
+
notEquals(other) {
|
|
109
|
+
return !this.equals(other);
|
|
110
|
+
}
|
|
111
|
+
/** Whether this quantity is less than `other`. */
|
|
112
|
+
lessThan(other) {
|
|
113
|
+
return this.magnitude < other.in(this.unit);
|
|
114
|
+
}
|
|
115
|
+
/** Whether this quantity is greater than `other`. */
|
|
116
|
+
greaterThan(other) {
|
|
117
|
+
return this.magnitude > other.in(this.unit);
|
|
118
|
+
}
|
|
119
|
+
/** Whether this quantity is less than or equal to `other`. */
|
|
120
|
+
lessThanOrEqual(other) {
|
|
121
|
+
return this.magnitude <= other.in(this.unit);
|
|
122
|
+
}
|
|
123
|
+
/** Whether this quantity is greater than or equal to `other`. */
|
|
124
|
+
greaterThanOrEqual(other) {
|
|
125
|
+
return this.magnitude >= other.in(this.unit);
|
|
126
|
+
}
|
|
127
|
+
/** Alias for {@link equals}. */
|
|
128
|
+
eq(other) {
|
|
129
|
+
return this.equals(other);
|
|
130
|
+
}
|
|
131
|
+
/** Alias for {@link notEquals}. */
|
|
132
|
+
ne(other) {
|
|
133
|
+
return this.notEquals(other);
|
|
134
|
+
}
|
|
135
|
+
/** Alias for {@link lessThan}. */
|
|
136
|
+
lt(other) {
|
|
137
|
+
return this.lessThan(other);
|
|
138
|
+
}
|
|
139
|
+
/** Alias for {@link greaterThan}. */
|
|
140
|
+
gt(other) {
|
|
141
|
+
return this.greaterThan(other);
|
|
142
|
+
}
|
|
143
|
+
/** Alias for {@link lessThanOrEqual}. */
|
|
144
|
+
lte(other) {
|
|
145
|
+
return this.lessThanOrEqual(other);
|
|
146
|
+
}
|
|
147
|
+
/** Alias for {@link greaterThanOrEqual}. */
|
|
148
|
+
gte(other) {
|
|
149
|
+
return this.greaterThanOrEqual(other);
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Compare with `other` (in this quantity's unit): `-1` if this is smaller, `1`
|
|
153
|
+
* if larger, `0` if equal. Suitable as an `Array#sort` comparator.
|
|
154
|
+
*/
|
|
155
|
+
compareTo(other) {
|
|
156
|
+
const value = other.in(this.unit);
|
|
157
|
+
if (this.magnitude < value) {
|
|
158
|
+
return -1;
|
|
159
|
+
}
|
|
160
|
+
if (this.magnitude > value) {
|
|
161
|
+
return 1;
|
|
162
|
+
}
|
|
163
|
+
return 0;
|
|
164
|
+
}
|
|
165
|
+
/** Whether this quantity's magnitude is exactly zero. */
|
|
166
|
+
isZero() {
|
|
167
|
+
return this.magnitude === 0;
|
|
168
|
+
}
|
|
169
|
+
/** Whether this quantity's magnitude is greater than zero. */
|
|
170
|
+
isPositive() {
|
|
171
|
+
return this.magnitude > 0;
|
|
172
|
+
}
|
|
173
|
+
/** Whether this quantity's magnitude is less than zero. */
|
|
174
|
+
isNegative() {
|
|
175
|
+
return this.magnitude < 0;
|
|
176
|
+
}
|
|
21
177
|
/**
|
|
22
178
|
* Parse a string into a `Quantity` using a dimension's known units and aliases.
|
|
23
179
|
*
|
|
@@ -50,6 +206,18 @@ class Quantity {
|
|
|
50
206
|
}
|
|
51
207
|
return new Quantity(finest.fromBase(total), finest);
|
|
52
208
|
}
|
|
209
|
+
/** The smallest of the given quantities (by value); requires at least one. */
|
|
210
|
+
static min(first, ...rest) {
|
|
211
|
+
return rest.reduce((smallest, q) => (q.lessThan(smallest) ? q : smallest), first);
|
|
212
|
+
}
|
|
213
|
+
/** The largest of the given quantities (by value); requires at least one. */
|
|
214
|
+
static max(first, ...rest) {
|
|
215
|
+
return rest.reduce((largest, q) => (q.greaterThan(largest) ? q : largest), first);
|
|
216
|
+
}
|
|
217
|
+
/** The sum of the given quantities, in the first one's unit; requires at least one. */
|
|
218
|
+
static sum(first, ...rest) {
|
|
219
|
+
return rest.reduce((total, q) => total.plus(q), first);
|
|
220
|
+
}
|
|
53
221
|
}
|
|
54
222
|
exports.Quantity = Quantity;
|
|
55
223
|
/** Resolve a token to a single unit, disambiguating shared aliases by system. */
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { Dimension } from "./Dimension";
|
|
2
|
+
import type { Unit } from "./Unit";
|
|
3
|
+
/** A metric (SI) prefix: a name, symbol, and power-of-ten factor. */
|
|
4
|
+
export interface SiPrefix {
|
|
5
|
+
name: string;
|
|
6
|
+
symbol: string;
|
|
7
|
+
factor: number;
|
|
8
|
+
}
|
|
9
|
+
/** The full set of SI prefixes, yotta (1e24) down to yocto (1e-24). */
|
|
10
|
+
export declare const SI_PREFIXES: readonly SiPrefix[];
|
|
11
|
+
/** SI prefixes for fractions only (deci and smaller) — for units like seconds. */
|
|
12
|
+
export declare const SI_SUBMULTIPLE_PREFIXES: readonly SiPrefix[];
|
|
13
|
+
/** The unit a set of metric prefixes is generated relative to. */
|
|
14
|
+
export interface PrefixReference {
|
|
15
|
+
/** Singular unit name, e.g. "meter" → "kilometer", "millimeter", … */
|
|
16
|
+
name: string;
|
|
17
|
+
/** Primary symbol, e.g. "m" → "km", "mm", … */
|
|
18
|
+
symbol: string;
|
|
19
|
+
/** Scale of the reference relative to its dimension's base (meter → 1, gram → 0.001). */
|
|
20
|
+
scale: number;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Define metric-prefixed variants of a reference unit on a dimension. Each
|
|
24
|
+
* variant is named `${prefix}${reference.name}` (e.g. "kilometer") with scale
|
|
25
|
+
* `reference.scale * prefix.factor`, plus a `${prefix.symbol}${reference.symbol}`
|
|
26
|
+
* alias and a plural (and an ASCII "u" form for micro).
|
|
27
|
+
*
|
|
28
|
+
* Prefixes whose generated name already exists on the dimension are skipped, so
|
|
29
|
+
* a base like "kilogram" is left intact when prefixing "gram".
|
|
30
|
+
*
|
|
31
|
+
* Returns the created units keyed by name, for spreading into a
|
|
32
|
+
* {@link MeasurementSystem} or destructuring into named exports.
|
|
33
|
+
*/
|
|
34
|
+
export declare function definePrefixed(dimension: Dimension, reference: PrefixReference, prefixes?: readonly SiPrefix[]): Record<string, Unit>;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SI_SUBMULTIPLE_PREFIXES = exports.SI_PREFIXES = void 0;
|
|
4
|
+
exports.definePrefixed = definePrefixed;
|
|
5
|
+
/** The full set of SI prefixes, yotta (1e24) down to yocto (1e-24). */
|
|
6
|
+
exports.SI_PREFIXES = [
|
|
7
|
+
{ name: "yotta", symbol: "Y", factor: 1e24 },
|
|
8
|
+
{ name: "zetta", symbol: "Z", factor: 1e21 },
|
|
9
|
+
{ name: "exa", symbol: "E", factor: 1e18 },
|
|
10
|
+
{ name: "peta", symbol: "P", factor: 1e15 },
|
|
11
|
+
{ name: "tera", symbol: "T", factor: 1e12 },
|
|
12
|
+
{ name: "giga", symbol: "G", factor: 1e9 },
|
|
13
|
+
{ name: "mega", symbol: "M", factor: 1e6 },
|
|
14
|
+
{ name: "kilo", symbol: "k", factor: 1e3 },
|
|
15
|
+
{ name: "hecto", symbol: "h", factor: 1e2 },
|
|
16
|
+
{ name: "deca", symbol: "da", factor: 1e1 },
|
|
17
|
+
{ name: "deci", symbol: "d", factor: 1e-1 },
|
|
18
|
+
{ name: "centi", symbol: "c", factor: 1e-2 },
|
|
19
|
+
{ name: "milli", symbol: "m", factor: 1e-3 },
|
|
20
|
+
{ name: "micro", symbol: "µ", factor: 1e-6 },
|
|
21
|
+
{ name: "nano", symbol: "n", factor: 1e-9 },
|
|
22
|
+
{ name: "pico", symbol: "p", factor: 1e-12 },
|
|
23
|
+
{ name: "femto", symbol: "f", factor: 1e-15 },
|
|
24
|
+
{ name: "atto", symbol: "a", factor: 1e-18 },
|
|
25
|
+
{ name: "zepto", symbol: "z", factor: 1e-21 },
|
|
26
|
+
{ name: "yocto", symbol: "y", factor: 1e-24 },
|
|
27
|
+
];
|
|
28
|
+
/** SI prefixes for fractions only (deci and smaller) — for units like seconds. */
|
|
29
|
+
exports.SI_SUBMULTIPLE_PREFIXES = exports.SI_PREFIXES.filter((prefix) => prefix.factor < 1);
|
|
30
|
+
/**
|
|
31
|
+
* Define metric-prefixed variants of a reference unit on a dimension. Each
|
|
32
|
+
* variant is named `${prefix}${reference.name}` (e.g. "kilometer") with scale
|
|
33
|
+
* `reference.scale * prefix.factor`, plus a `${prefix.symbol}${reference.symbol}`
|
|
34
|
+
* alias and a plural (and an ASCII "u" form for micro).
|
|
35
|
+
*
|
|
36
|
+
* Prefixes whose generated name already exists on the dimension are skipped, so
|
|
37
|
+
* a base like "kilogram" is left intact when prefixing "gram".
|
|
38
|
+
*
|
|
39
|
+
* Returns the created units keyed by name, for spreading into a
|
|
40
|
+
* {@link MeasurementSystem} or destructuring into named exports.
|
|
41
|
+
*/
|
|
42
|
+
function definePrefixed(dimension, reference, prefixes = exports.SI_PREFIXES) {
|
|
43
|
+
const units = {};
|
|
44
|
+
for (const prefix of prefixes) {
|
|
45
|
+
const name = `${prefix.name}${reference.name}`;
|
|
46
|
+
if (dimension.get(name)) {
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
const aliases = [`${prefix.symbol}${reference.symbol}`, `${name}s`];
|
|
50
|
+
if (prefix.name === "micro") {
|
|
51
|
+
aliases.push(`u${reference.symbol}`);
|
|
52
|
+
}
|
|
53
|
+
units[name] = dimension.unit(name, reference.scale * prefix.factor, aliases);
|
|
54
|
+
}
|
|
55
|
+
return units;
|
|
56
|
+
}
|
package/dist/systems/metric.d.ts
CHANGED
package/dist/systems/metric.js
CHANGED
|
@@ -6,13 +6,13 @@ const mass_1 = require("../dimensions/mass");
|
|
|
6
6
|
const temperature_1 = require("../dimensions/temperature");
|
|
7
7
|
const volume_1 = require("../dimensions/volume");
|
|
8
8
|
const MeasurementSystem_1 = require("../lib/MeasurementSystem");
|
|
9
|
-
/** The metric / SI standard. */
|
|
9
|
+
/** The metric / SI standard, including the full SI-prefixed unit ladders. */
|
|
10
10
|
exports.metric = new MeasurementSystem_1.MeasurementSystem("metric").add(
|
|
11
11
|
// length
|
|
12
|
-
length_1.meter,
|
|
12
|
+
length_1.meter, ...Object.values(length_1.metricLength),
|
|
13
13
|
// mass
|
|
14
|
-
mass_1.
|
|
14
|
+
mass_1.gram, mass_1.tonne, ...Object.values(mass_1.metricMass),
|
|
15
15
|
// volume
|
|
16
|
-
volume_1.liter, volume_1.
|
|
16
|
+
volume_1.liter, ...Object.values(volume_1.metricVolume),
|
|
17
17
|
// temperature
|
|
18
18
|
temperature_1.kelvin, temperature_1.celsius);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "measurable",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "Convert between units of measurement with custom and built-in systems",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"conversion",
|
|
@@ -49,5 +49,6 @@
|
|
|
49
49
|
"format": "biome format .",
|
|
50
50
|
"typecheck": "tsc --noEmit",
|
|
51
51
|
"test": "vitest run"
|
|
52
|
-
}
|
|
52
|
+
},
|
|
53
|
+
"readme": "# measurable\n\nConvert between units of measurement, with batteries-included common units and\nfirst-class support for defining your own.\n\n- **No drift** — each unit defines a single transform to its dimension's base\n unit; reverse conversions are derived, never stored, so they can't fall out of\n sync.\n- **Free chaining** — any unit converts to any other in the same dimension\n (e.g. `mile → inch`) without you defining every pair.\n- **Affine units** — temperature scales (°C/°F/K) and anything else needing an\n offset, not just a scale factor.\n- **Two orthogonal ideas** — a **dimension** decides what _can_ convert; a\n **measurement system** (metric/imperial/US) is a tag that never gates\n conversion but powers filtering, formatting, and parse disambiguation.\n\n## Installation\n\n```sh\nnpm install measurable\n```\n\n## Entry points\n\nThe package is split into three import paths so the core stays lean:\n\n| Import | What you get |\n| -------------------------- | ------------------------------------------------------------------------- |\n| `measurable` | The building blocks: `Quantity`, `Dimension`, `MeasurementSystem`, `Unit`, errors |\n| `measurable/dimensions` | Predefined dimensions and their units (`length`, `meter`, `volume`, …) |\n| `measurable/systems` | Predefined measurement systems (`metric`, `imperial`, `usCustomary`) |\n\n## Quick start\n\n```ts\nimport { Quantity } from \"measurable\";\nimport { meter, mile, celsius, fahrenheit } from \"measurable/dimensions\";\n\n// Convert: `.to()` returns a Quantity, `.in()` returns a raw number.\nnew Quantity(5, mile).to(meter).magnitude; // 8046.72\nnew Quantity(5, mile).in(meter); // 8046.72\n\n// Affine scales work the same way.\nnew Quantity(100, celsius).in(fahrenheit); // 212\n```\n\n## Concepts\n\n- **`Dimension`** — a kind of measurable quantity (length, volume, mass, …). It\n owns a canonical **base unit** and is where all conversion happens. A unit\n belongs to exactly one dimension.\n- **`Unit`** — a name plus a transform (`toBase` / `fromBase`) into its\n dimension's base unit. Created through a dimension's builder methods.\n- **`Quantity`** — a magnitude paired with a unit (e.g. `5 kilometer`).\n- **`MeasurementSystem`** — a cross-dimension tag (metric/imperial/…). A unit can\n belong to many; membership is optional and never affects whether a conversion\n is allowed.\n\n## Built-in dimensions\n\nImport any dimension or unit from `measurable/dimensions`:\n\n| Dimension | Base | Units (a selection) |\n| ------------- | ---------- | ----------------------------------------------------------------------------------- |\n| `length` | `meter` | `kilometer`, `centimeter`, `millimeter`, `inch`, `foot`, `yard`, `mile` |\n| `volume` | `liter` | `milliliter`, `us*`/`imperial*` `Gallon`/`Quart`/`Pint`/`Gill`/`FluidOunce`, `cup`, `tablespoon`, `teaspoon` |\n| `mass` | `gram` | `kilogram`, `milligram`, `tonne`, `pound`, `ounce`, `stone`, `shortTon`, `longTon` |\n| `time` | `second` | `millisecond`, `minute`, `hour`, `day`, `week` |\n| `temperature` | `kelvin` | `celsius`, `fahrenheit` |\n| `angle` | `radian` | `degree`, `gradian`, `turn` |\n| `force` | `newton` | `kilonewton`, `dyne`, `poundForce`, `kilogramForce` |\n\nThe metric units carry the **full SI prefix ladder** (yotta → yocto), generated for\nyou: `length`, `mass`, `volume`, and `force` get every prefix (so `kilogram`\nitself is just the kilo-prefixed gram), while `time` and `angle` get the\nfractional prefixes only (e.g.\n`millisecond`, `microradian`). So `decimeter`, `hectometer`, `megagram`,\n`kiloliter`, `nanosecond`, etc. are all available and parse from their symbols\n(`dm`, `hm`, `Mg`, `kL`, `ns`, and `µm`/`um` for micro). You can apply the same\nladder to your own dimensions with `definePrefixed` (see below).\n\n## Built-in measurement systems\n\nImport `metric`, `imperial`, or `usCustomary` from `measurable/systems`.\n\n```ts\nimport { foot } from \"measurable/dimensions\";\nimport { imperial, usCustomary, metric } from \"measurable/systems\";\n\nimperial.has(foot); // true — a unit can belong to several systems\nusCustomary.has(foot); // true\nmetric.has(foot); // false\n```\n\n### Listing units in a system\n\n```ts\nimport { length } from \"measurable/dimensions\";\nimport { metric } from \"measurable/systems\";\n\nmetric.in(length).map((u) => u.name); // [\"meter\", \"kilometer\", \"centimeter\", \"millimeter\"]\n```\n\n### Best-fit formatting\n\n`express` re-expresses a quantity in a system's most readable unit (the largest\nunit whose magnitude is still ≥ 1):\n\n```ts\nimport { Quantity } from \"measurable\";\nimport { meter } from \"measurable/dimensions\";\nimport { metric, imperial } from \"measurable/systems\";\n\nmetric.express(new Quantity(5000, meter)); // Quantity(5, kilometer)\nimperial.express(new Quantity(5000, meter)); // Quantity(3.107…, mile)\n```\n\nA `Quantity` also has a `toString()` that renders `\"<magnitude> <unit name>\"`\n(e.g. `new Quantity(5, kilometer).toString()` → `\"5 kilometer\"`), and `round(decimals)`\nto trim the magnitude for display (`new Quantity(1.6213, mile).round(2)` → `1.62 mile`).\n\n## Parsing strings\n\n`Quantity.parse(input, dimension, options?)` reads a string into a `Quantity`.\nCompound inputs are summed and returned in the finest unit present:\n\n```ts\nimport { Quantity } from \"measurable\";\nimport { length, time } from \"measurable/dimensions\";\n\nQuantity.parse(\"1km\", length); // Quantity(1, kilometer)\nQuantity.parse(\"5 hr\", time); // Quantity(5, hour)\nQuantity.parse(\"5hr 20min\", time); // Quantity(320, minute)\n```\n\n### Ambiguous aliases\n\nSome names mean different things in different systems — a US gallon (3.785 L) is\nnot an imperial gallon (4.546 L), and `ton` could be short or long. These are\ndistinct units that share an alias, so an unqualified parse throws; pass a\n`prefer`red system to disambiguate:\n\n```ts\nimport { Quantity, AmbiguousUnitError } from \"measurable\";\nimport { volume, mass } from \"measurable/dimensions\";\nimport { usCustomary, imperial } from \"measurable/systems\";\n\nQuantity.parse(\"1 gallon\", volume); // throws AmbiguousUnitError\nQuantity.parse(\"1 gallon\", volume, { prefer: usCustomary }).unit.name; // \"usGallon\"\nQuantity.parse(\"1 ton\", mass, { prefer: imperial }).unit.name; // \"longTon\"\n```\n\nConversion itself is governed only by the dimension, so cross-system conversions\nalways work regardless of tags:\n\n```ts\nimport { shortTon, tonne } from \"measurable/dimensions\";\n\nnew Quantity(1, shortTon).in(tonne); // 0.90718474\n```\n\n## Arithmetic\n\nQuantities can be combined. `plus`/`minus` take another `Quantity` (converted into\nthe receiver's unit first, so the operands may use different units of the same\ndimension); `times`/`dividedBy` apply a dimensionless scalar, and `negate`/`abs`\ntransform the magnitude. All return a **new** `Quantity` in the receiver's unit and\nleave the operands untouched.\n\n```ts\nimport { Quantity } from \"measurable\";\nimport { kilometer, mile } from \"measurable/dimensions\";\n\nnew Quantity(1, mile).plus(new Quantity(1, kilometer)); // Quantity(1.6213…, mile)\nnew Quantity(1, mile).minus(new Quantity(1, kilometer)); // Quantity(0.3786…, mile)\nnew Quantity(2, mile).times(3); // Quantity(6, mile)\nnew Quantity(6, mile).dividedBy(2); // Quantity(3, mile)\n```\n\nShort aliases are available: **`add`** (`plus`), **`sub`** (`minus`), **`mul`**\n(`times`), **`div`** (`dividedBy`).\n\nCombining different dimensions throws `InvalidConversionError`. Note that adding\n**affine** units (e.g. temperatures) is mathematically defined but physically\nquestionable, since it adds absolute points rather than a difference.\n\n## Ratios\n\n`ratioTo` divides two quantities of the **same dimension** and returns a plain\n(dimensionless) number — _how many of one fit in the other_:\n\n```ts\nimport { Quantity } from \"measurable\";\nimport { liter, milliliter } from \"measurable/dimensions\";\n\n// How many 250 mL servings are in a 2 L bottle?\nnew Quantity(2, liter).ratioTo(new Quantity(250, milliliter)); // 8\n```\n\nThis is different from `.in(unit)`: `.in(milliliter)` only uses the *unit* on the\nright (giving `2000`), whereas `ratioTo` also uses the other quantity's\n**magnitude** (the `250`), so it answers \"how many of *that quantity* fit in this\none.\" It's the inverse of scalar `times` — `b.times(a.ratioTo(b))` reconstructs\n`a`. Comparing different dimensions throws `InvalidConversionError`.\n\n## Comparison\n\n`equals`/`notEquals`/`lessThan`/`greaterThan`/`lessThanOrEqual`/`greaterThanOrEqual`\ncompare two quantities (the other is converted into the receiver's unit first),\nreturning a boolean. Comparing different dimensions throws `InvalidConversionError`.\n\n```ts\nimport { Quantity } from \"measurable\";\nimport { kilometer, meter } from \"measurable/dimensions\";\n\nnew Quantity(1, kilometer).equals(new Quantity(1000, meter)); // true\nnew Quantity(1, meter).lessThan(new Quantity(1, kilometer)); // true\nnew Quantity(1, kilometer).greaterThan(new Quantity(1, meter)); // true\n```\n\nShort aliases: **`eq`** (`equals`), **`ne`** (`notEquals`), **`lt`** (`lessThan`),\n**`gt`** (`greaterThan`), **`lte`** (`lessThanOrEqual`), **`gte`**\n(`greaterThanOrEqual`). Equality is exact, so values differing only by\nfloating-point rounding from a conversion may compare unequal.\n\n`compareTo(other)` returns `-1`, `0`, or `1`, suitable as an `Array#sort`\ncomparator: `quantities.sort((a, b) => a.compareTo(b))`.\n\n## Combining quantities\n\n`Quantity.min`/`max`/`sum` aggregate several quantities at once; `clamp` is an\ninstance method that bounds one quantity to a range. Each converts operands as\nneeded, so mixing dimensions throws `InvalidConversionError`.\n\n```ts\nimport { Quantity } from \"measurable\";\nimport { kilometer, meter } from \"measurable/dimensions\";\n\nconst a = new Quantity(1, kilometer);\nconst b = new Quantity(500, meter);\n\nQuantity.min(a, b); // Quantity(500, meter) — the smaller\nQuantity.max(a, b); // Quantity(1, kilometer) — the larger\nQuantity.sum(a, b); // Quantity(1.5, kilometer) — total, in a's unit\nb.clamp(a, new Quantity(2, kilometer)); // b bounded to [a, 2 km], in b's unit\n```\n\n## Defining your own units\n\nCreate a `Dimension` and add units through its builder methods. `scale` is how\nmany base units make up one of the unit being defined.\n\n```ts\nimport { Dimension, Quantity } from \"measurable\";\n\nconst data = new Dimension(\"data\");\nconst byte = data.base(\"byte\", [\"B\", \"bytes\"]); // the base unit (identity)\nconst kilobyte = data.unit(\"kilobyte\", 1024, [\"KB\"]);\nconst megabyte = data.unit(\"megabyte\", 1024 ** 2, [\"MB\"]);\n\nnew Quantity(2, megabyte).in(kilobyte); // 2048\n```\n\n### Affine units (offset, not just scale)\n\n```ts\nconst temperature = new Dimension(\"temperature\");\nconst kelvin = temperature.base(\"kelvin\", [\"K\"]);\n// value_in_base = value * scale + offset\nconst celsius = temperature.affine(\"celsius\", { scale: 1, offset: 273.15 }, [\"C\"]);\n```\n\n### Fully custom transforms\n\nFor anything non-linear, provide an explicit inverse pair:\n\n```ts\nconst dim = new Dimension(\"custom\");\ndim.base(\"base\");\ndim.custom(\"squared\", {\n toBase: (x) => x * x,\n fromBase: (x) => Math.sqrt(x),\n});\n```\n\n### Generating SI prefixes\n\n`definePrefixed` adds the metric prefix ladder to a reference unit and returns the\ncreated units keyed by name (skipping any name that already exists). Pass\n`SI_SUBMULTIPLE_PREFIXES` to generate fractions only.\n\n```ts\nimport { Dimension, Quantity, definePrefixed } from \"measurable\";\n\nconst data = new Dimension(\"data\");\nconst bit = data.base(\"bit\", [\"b\"]);\nconst prefixed = definePrefixed(data, { name: \"bit\", symbol: \"b\", scale: 1 });\n\nnew Quantity(1, prefixed.kilobit).in(bit); // 1000 (SI kilo = 1e3)\n```\n\n### Tagging units into a measurement system\n\n```ts\nimport { MeasurementSystem } from \"measurable\";\n\nconst si = new MeasurementSystem(\"si\").add(byte, kilobyte, megabyte);\nsi.has(kilobyte); // true\n```\n\n## API reference\n\n### `Dimension`\n\n- `new Dimension(name)`\n- `.base(name, aliases?)` — define the canonical base unit\n- `.unit(name, scale, aliases?)` — linear unit (`scale` base units per unit)\n- `.affine(name, { scale, offset }, aliases?)` — linear with additive offset\n- `.custom(name, { toBase, fromBase }, aliases?)` — arbitrary inverse pair\n- `.convert(value, from, to)` — convert a raw number between two of its units\n- `.get(token)` — units matching a name/alias (`Unit[] | undefined`)\n- `.has(unit)`, `.units`, `.baseUnit`\n\n### `Unit`\n\nA passive handle, normally created via a dimension's builder methods rather than\n`new Unit` directly. Read-only properties:\n\n- `.name` — the unit's canonical name\n- `.dimension` — the `Dimension` it belongs to\n- `.toBase(value)` → `number` — convert a value in this unit to base units\n- `.fromBase(value)` → `number` — convert a value in base units to this unit\n\n### `Quantity`\n\n- `new Quantity(magnitude, unit)`\n- `.to(target)` → `Quantity`\n- `.in(target)` → `number`\n- `.toString()` → `string` — e.g. `\"5 kilometer\"`\n- `.plus(other)` / `.minus(other)` → `Quantity` — add/subtract another quantity (aliases: `add` / `sub`)\n- `.times(factor)` / `.dividedBy(divisor)` → `Quantity` — scale by a number (aliases: `mul` / `div`)\n- `.ratioTo(other)` → `number` — dimensionless ratio (how many of `other` fit in this)\n- `.negate()` / `.abs()` → `Quantity`\n- `.clamp(lower, upper)` → `Quantity` — bound to a range, in this unit\n- `.round(decimals?)` → `Quantity` — round the magnitude (default 0 decimals)\n- `.equals(other)` / `.notEquals(other)` → `boolean` (aliases: `eq` / `ne`)\n- `.lessThan(other)` / `.greaterThan(other)` → `boolean` (aliases: `lt` / `gt`)\n- `.lessThanOrEqual(other)` / `.greaterThanOrEqual(other)` → `boolean` (aliases: `lte` / `gte`)\n- `.compareTo(other)` → `-1 | 0 | 1` — sort comparator\n- `.isZero()` / `.isPositive()` / `.isNegative()` → `boolean`\n- `Quantity.min(...quantities)` / `Quantity.max(...quantities)` / `Quantity.sum(...quantities)` → `Quantity`\n- `Quantity.parse(input, dimension, { prefer? })` → `Quantity`\n\n### `MeasurementSystem`\n\n- `new MeasurementSystem(name)`\n- `.add(...units)`, `.has(unit)`\n- `.in(dimension)` → `Unit[]`\n- `.express(quantity)` → `Quantity`\n\n### Errors\n\n- `InvalidConversionError` — units are from different dimensions\n- `UnknownUnitError` — a parsed token matches no unit\n- `AmbiguousUnitError` — a parsed token matches several units and no `prefer` was given\n\n## License\n\nISC\n"
|
|
53
54
|
}
|