ts-quantities
Originally a fork of gentooboontoo/js-quantities rewritten in typescript.
Installing ts-quantities
Node
Install it in your project
npm install --save ts-quantities
Import it !
Using ts-quantities
Qty
ts-quantities heavily relies on Qty
objects. To create Qty
objects, use its constructor using new
.
qty = new Qty'23 ft';
Qty
constructor accepts strings, numbers and Qty
instances as
initializing values.
If scalars and their respective units are available programmatically, the two argument signature may be useful:
qty = new Qty124, 'cm'; // => 1.24 meter
qty = new Qty'1m'; // => 1 meterqty = new Qty'm'; // => 1 meter (scalar defaults to 1) qty = new Qty'1 N*m';qty = new Qty'1 N m'; // * is optional qty = new Qty'1 m/s'; qty = new Qty'1 m^2/s^2';qty = new Qty'1 m^2 s^-2'; // negative powersqty = new Qty'1 m2 s-2'; // ^ is optional qty = new Qty'1 m^2 kg^2 J^2/s^2 A'; qty = new Qty'1.5'; // unitless quantityqty = new Qty15; // number as initializing value qty = new Qty'1 attoparsec/microfortnight'; qtyCopy = new Qtyqty; // quantity could be copied when used as // initializing value
Parsing a quantity manually
Qty.parse
utility method is also provided to parse and create
quantities from strings. Unlike the constructor, it will return null
instead of throwing an error when parsing an invalid quantity.
static parsevalue: string: Qty Qty.parse'1 m'; // => 1 meterQty.parse'foo'; // => null
Available well-known kinds
static getKinds: string Qty.getKinds; // => Array of names of every well-known kind of units
Available units of a particular kind
static getUnitskind?: string: string Qty.getUnits'currency'; // => [ 'dollar', 'cents' ]Qty.getUnits; // All units, alphebetically sorted => [ 'acre','Ah','ampere','AMU','angstrom', ...]
Alternative names of a unit
static getAliasesunitName: string: string Qty.getAliases'm'; // => [ 'm', 'meter', 'meters', 'metre', 'metres' ]
Quantity compatibility, kind and various queries
public isCompatibleother: Qty | string: booleanqty1.isCompatibleqty2; // => true or false public kind: stringqty.kind; // => 'length', 'area', etc... public isUnitless: booleanqty.isUnitless; // => true or false public isBase: booleanqty.isBase; // => true if quantity is represented with base units
Conversion
public toBase: Qtyqty.toBase; // converts to SI units (10 cm => 0.1 m) (new instance) public toFloat: numberqty.toFloat; // returns scalar of unitless quantity // (otherwise throws error) public toQty | string: Qtyqty.to'm'; // converts quantity to meter if compatible // or throws an error (new instance)qty1.toqty2; // converts quantity to same unit of qty2 if compatible // or throws an error (new instance) public inverse: Qtyqty.inverse; // converts quantity to its inverse // ('100 m/s' => '0.01 s/m')// Inverses can be used, but there is no special checking to// rename the unitsnew Qty'10ohm'.inverse; // '0.1/ohm' // (not '0.1S', although they are equivalent)// however, the 'to' command will convert between inverses alsonew Qty'10ohm'.to'S'; // '0.1S' public convertSingleUnitbaseUnit: string, targetUnit: string: Qty// Converts the selected baseUnit into the target unit. Others units remain untouched.new Qty'0.14 USD/kWh'.convertSingleUnit'kWh', 'MWh'; // 140 USD/MWhnew Qty'4000 m2'.convertSingleUnit'm', 'km'; // 0.004 km2
Mass conversion
Qty.swiftConverter()
is a fast way to efficiently convert large array of
Number values. It configures a function accepting a value or an array of Number
values to convert.
static swiftConvertersrcUnits: string, dstUnits: string:number | number ; // Configures converter // Converting single value; // => 2.278..// Converting large array of values; // => [2.278.., 4.556.., ...]
The main drawback of this conversion method is that it does not take care of rounding issues.
Comparison
public eqother: Qty: booleanqty1.eqqty2; // => true if both quantities are equal (1m == 100cm => true) public sameother: Qty: booleanqty1.sameqty2; // => true if both quantities are same (1m == 100cm => false) public ltother: Qty: booleanqty1.ltqty2; // => true if qty1 is stricty less than qty2 public lteother: Qty: booleanqty1.lteqty2; // => true if qty1 is less than or equal to qty2 public gtother: Qty: booleanqty1.gtqty2; // => true if qty1 is stricty greater than qty2 public gteother: Qty: booleanqty1.gteqty2; // => true if qty1 is greater than or equal to qty2 public compareToother: Qty: numberqty1.compareToqty2; // => -1 if qty1 < qty2, // => 0 if qty1 == qty2, // => 1 if qty1 > qty2
Operators
public addother: Qty | string | number: Qty // other should be unit compatible.public subother: Qty | string | number: Qty // other should be unit compatible.public mulother: Qty | string | number: Qtypublic divother: Qty | string | number: Qty
Rounding
Qty#toPrec(precision)
: returns the nearest multiple of quantity passed as
precision.
public toPrecprecQuantity: Qty | string | number: Qty ;qty.toPrec'ft'; // => 5 ftqty.toPrec'0.5 ft'; // => 5 ftqty.toPrec'0.25 ft'; // => 5.25 ftqty.toPrec'0.1 ft'; // => 5.2 ftqty.toPrec'0.05 ft'; // => 5.15 ftqty.toPrec'0.01 ft'; // => 5.17 ftqty.toPrec'0.00001 ft'; // => 5.17 ftqty.toPrec'2 ft'; // => 6 ftqty.toPrec'2'; // => 6 ft ;qty.toPrec'dm'; // => 6.4 mqty.toPrec'cm'; // => 6.38 mqty.toPrec'mm'; // => 6.378 mqty.toPrec'5 cm'; // => 6.4 mqty.toPrec'10 m'; // => 10 mqty.toPrec01; // => 6.3 m ;qty.toPrec'0.1 bar'; // => 1.15 MPa
Formatting quantities
Qty#toString
returns a string using the canonical form of the quantity (that
is it could be seamlessly reparsed by Qty
).
public toStringtoUnits?: string: string ;qty.toString; // => '1.146 MPa'
As a shorthand, units could be passed to Qty#toString
and is equivalent to
successively call Qty#to
then Qty#toString
.
;qty.toString'bar'; // => '11.46 bar'qty.to'bar'.toString; // => '11.46 bar'
Qty#toString
could also be used with any method from Qty
to make some sort
of formatting. For instance, one could use Qty#toPrec
to fix the maximum
number of decimals:
;qty.toPrec01.toString; // => '1.1 MPa'qty.to'bar'.toPrec01.toString; // => '11.5 bar'
For advanced formatting needs as localization, specific rounding or any other
custom customization, quantities can be transformed into strings through
Qty#format
according to optional target units and formatter. If target units
are specified, the quantity is converted into them before formatting.
Such a string is not intended to be reparsed to construct a new instance of
Qty
(unlike output of Qty#toString
).
If no formatter is specified, quantities are formatted according to default
ts-quantities' formatter and is equivalent to Qty#toString
.
;public formatformatter?: Formatter: string;public formattargetUnits?: string, formatter?: Formatter: string;
;qty.format; // same units, default formatter => '1.234 m'qty.format'cm'; // converted to 'cm', default formatter => '123.45 cm'
Qty#format
could delegates formatting to a custom formatter if required. A
formatter is a callback function accepting scalar and units as parameters and
returning a formatted string representing the quantity.
; ; // same units, custom formatter => '1.12 m'qty.formatconfigurableRoundingFormatter2; // convert to 'cm', custom formatter => '123.4 cm'qty.format'cm', configurableRoundingFormatter1;
Custom formatter can be configured globally by setting Qty.formatter
.
static formatter: Formatter; Qty.formatter = configurableRoundingFormatter2;;qty.format; // same units, current default formatter => '1.12 m'
Temperatures
Like ruby-units, ts-quantities makes a distinction between a temperature (which technically is a property) and degrees of temperature (which temperatures are measured in).
Temperature units (i.e., 'tempK') can be converted back and forth, and will take into account the differences in the zero points of the various scales. Differential temperature (e.g., '100 degC') units behave like most other units.
new Qty'37 tempC'.to'tempF' // => 98.6 tempF
ts-quantities will throw an error if you attempt to create a temperature unit that would fall below absolute zero.
Unit math on temperatures is fairly limited.
new Qty'100 tempC'.add'10 degC' // 110 tempCnew Qty'100 tempC'.sub'10 degC' // 90 tempCnew Qty'100 tempC'.add'50 tempC' // throws errornew Qty'100 tempC'.sub'50 tempC' // 50 degCnew Qty'50 tempC'.sub'100 tempC' // -50 degCnew Qty'100 tempC'.mulscalar // 100*scalar tempCnew Qty'100 tempC'.divscalar // 100/scalar tempCnew Qty'100 tempC'.mulqty // throws errornew Qty'100 tempC'.divqty // throws errornew Qty'100 tempC*unit' // throws errornew Qty'100 tempC/unit' // throws errornew Qty'100 unit/tempC' // throws errornew Qty'100 tempC'.inverse // throws error
new Qty'100 tempC'.to'degC' // => 100 degC
This conversion references the 0 point on the scale of the temperature unit
new Qty'100 degC'.to'tempC' // => -173.15 tempC
These conversions are always interpreted as being relative to absolute zero. Conversions are probably better done like this...
new Qty'0 tempC'.add'100 degC' // => 100 tempC
Errors
Every error thrown by ts-quantities is an instance of Qty.Error
.
try catcherror
Tests
Tests are implemented with Jasmine (https://github.com/pivotal/jasmine).
To execute specs through jasmine-node
, launch:
npm install -g jasmine-node
npm run test
Contribute
Feedback and contributions are welcomed.
Pull requests must pass tests and linting. Please make sure that npm run test
and npm run lint
return no errors before submitting.