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

System Boundaries ​

Money usually crosses several boundaries. The safest shape depends on where the value is crossing.

money-safe focuses on amount shape: parsing, integer minor units, arithmetic, allocation, formatting, and serialized payloads. It does not own exchange rates, accounting ledgers, tax policy, provider orchestration, or product pricing rules.

Browser and public API input ​

Use decimal strings:

json
{
  "amount": "19.99",
  "currency": "CNY"
}
ts
const value = amount(payload.amount, payload.currency);

Database and payment providers ​

Use minor units:

sql
amount_minor BIGINT NOT NULL,
currency CHAR(3) NOT NULL,
minor_unit SMALLINT NOT NULL
ts
const value = amount.minor(row.amount_minor, row.currency, {
  minorUnit: row.minor_unit
});

Service-to-service payloads ​

Use serialized money:

json
{
  "amountMinor": "1999",
  "currency": "CNY",
  "minorUnit": 2
}
ts
const value = amount.fromJSON(payload);

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

Display ​

Format only at display boundaries:

ts
amount('19.99', 'CNY').format('zh-CN');

Do not feed formatted strings back into business logic.

Business policy stays in your app ​

Keep policy decisions next to the business flow that owns them:

  • Which tax rate applies.
  • Which payment provider receives the payload.
  • Which ledger account records the movement.
  • Which exchange rate source is trusted.

Use money-safe for the money value that crosses those boundaries, not as the owner of those policies.