money-safe
v0.1.0TYPE-SAFE MONEY
DOCS INTERFACE · GUIDE / RECIPES / REFERENCE · MINOR UNITS STAY EXPLICIT
API Reference

API Reference

Which Entry To Use

Use the entry that matches the boundary you are crossing:

ts
amount('19.99', 'CNY');              // form or public API input
amount.decimal('19.99', 'CNY');      // same, but explicit in dense code
amount.minor(1999, 'CNY');           // database, ledger, payment provider
amount.bigint('900719925474099.93', 'USD');
amount.fromNumber(19.995, 'USD', { rounding: 'half-up' });
amount.fromJSON({ amountMinor: '1999', currency: 'CNY', minorUnit: 2 });

The main amount(...) entry accepts decimal strings, not JavaScript decimal numbers. Existing number values must use fromNumber(...) so the rounding decision is visible.

Chain API

ts
amount('19.99', 'CNY');
amount.decimal('19.99', 'CNY');
amount.minor(1999, 'CNY');
amount.bigint('900719925474099.93', 'USD');
amount.fromNumber(19.995, 'USD', { rounding: 'half-up' });
amount.fromJSON({ amountMinor: '1999', currency: 'CNY', minorUnit: 2 });

Chain Methods

ts
value.plus('5.00');
value.plusMinor(500);
value.minus('1.00');
value.minusMinor(100);
value.times('0.85', { rounding: 'half-up' });
value.divide(3, { rounding: 'half-up' });
value.split(3);
value.allocate([2, 1]);
value.format('zh-CN');
value.toDecimal();
value.toMinor();
value.toMoney();
value.toJSON();

format(...) is for display boundaries. Use toJSON() or toMinor() when sending values to infrastructure.

Serialized Payloads

ts
const payload = amount('19.99', 'CNY').toJSON();

payload;
// { amountMinor: '1999', currency: 'CNY', minorUnit: 2 }

amount.fromJSON(payload).toDecimal();
// '19.99'

amountMinor is a string in JSON so large values can move across services without passing through JavaScript Number.

Pure functions

ts
money(1999, 'CNY');
parseMoney('19.99', 'CNY');
parseMoneyBigInt('900719925474099.93', 'USD');
parseMoneyFromNumber(19.995, 'USD', { rounding: 'half-up' });
add(left, right);
subtract(left, right);
multiply(value, '0.85');
divide(value, 3);
allocate(value, [2, 1]);
distribute(value, 3);
formatMoney(value, { locale: 'zh-CN' });
toJSON(value);
fromJSON(payload);

Pure functions use the same value model as the chain API. They are useful in tests, reducers, and codebases that prefer function composition.

Rounding Boundaries

ts
value.times('0.85', { rounding: 'half-up' });
value.divide(3, { rounding: 'half-even' });
amount.fromNumber(19.995, 'USD', { rounding: 'half-up' });

Rounding is required when converting existing decimal numbers and should be explicit when ratio math cannot land exactly on a minor unit.

Errors

  • InvalidAmountError
  • InvalidCurrencyError
  • CurrencyMismatchError
  • UnsafeIntegerError
  • InvalidRatioError
  • AllocationError