Dinero.js: money arithmetic in JavaScript without float drift
Create, calculate, and format money in JavaScript and TypeScript
At a glance
- What is it?
- Dinero.js is an immutable, side-effect-free library for creating, calculating and formatting monetary values in JavaScript and TypeScript. Its main draw is that amounts are plain integers plus a currency object, and its main cost is that formatting, locale and rounding decisions stay in your hands.
- Who is it for?
- Adopt Dinero.js when you already know your currency, your rounding rule and your locale, and you want amounts to be integers that survive arithmetic. Skip it when you need a currency-formatting wrapper around Intl.NumberFormat, since the project's own FAQ page is titled "Why no currency formatting".
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 2 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 3, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem Dinero.js solves is JavaScript's number type
JavaScript has one numeric type for everyday arithmetic, and it is a binary floating-point double. Money is decimal. The mismatch shows up as soon as you add 0.1 and 0.2, and it shows up again when you divide an amount and need to decide where the remainder goes. Dinero.js takes the position that a monetary value should not be a float at all. A Dinero object holds an amount as a whole number and a currency definition that describes how many decimal places that amount has. Arithmetic happens on the integer, and the currency carries the scale. The README frames the motivation directly: "Money is complex, and the primitives of the language aren't enough to properly represent it." The intended audience is application developers who move money through code, whether that is a shopping cart, an invoice builder or an expense splitter. The repository ships worked examples under examples/ named cart-react, cart-vue, expense-splitter, invoice-builder, portfolio-tracker and pricing-react, which is a fair map of the use cases the maintainers had in mind.
Amounts are integers, currencies carry the scale
The core object is small. You construct it with an amount and a currency, and every exported function takes Dinero objects and returns new ones. There is no mutation and no internal state to synchronize. The README states the design rule plainly: "every operation returns a new object, no side effects." That matters more than it sounds. If add() returned a mutated object, two parts of an application holding the same value would silently affect each other. Because it returns a new object, you can pass a Dinero value into a function and know the caller's value is unchanged.
The second design decision is that functions are separate imports rather than methods. You import add, toDecimal or whatever you need from the package root, and a bundler drops the rest. The README calls this tree-shakeable and pairs it with the immutability claim: "Every function in dinero.js is side-effect free, allowing you only to bundle exactly what you use." In practice this means the library's footprint tracks how many operations you actually call, not how large the package is.
The third decision concerns precision. The README lists "Pluggable precision: use number by default or bigint for large amounts." So the default representation is a JavaScript number used as an integer, and there is an opt-in path for amounts that exceed what a double can hold exactly. The repository also lists big.js among its devDependencies, which the documentation's precision and large numbers guide is the place to check if you need to understand how the two relate. The fourth decision is non-decimal support: the README advertises "support for any base, including multi-subdivision currencies," which is the case that breaks libraries assuming every currency has two decimal places.
Installing Dinero.js and doing a first calculation
The README gives npm and Yarn as the two install paths. Nothing else is required; there is no build step, no configuration file and no runtime dependency to wire up.
npm install dinero.jsWith the package in place, the quick start constructs two amounts and adds them. Note that the currency is imported from a subpath, not from the package root, and that the amount is written in the currency's smallest unit.
import { dinero, add, toDecimal } from 'dinero.js';
import { USD } from 'dinero.js/currencies';
const d1 = dinero({ amount: 500, currency: USD });
const d2 = dinero({ amount: 800, currency: USD });
const total = add(d1, d2);
toDecimal(total); // "13.00"The comment in the README shows the expected result: the two amounts are 5.00 and 8.00 USD, and toDecimal returns the string "13.00". Two things are worth noticing before you write more code. First, 500 is not five dollars, it is five hundred cents, which is why the result is 13.00 rather than 1300. Second, toDecimal returns a string, not a number. That is deliberate: handing the value back as a float would undo the precision the library exists to protect. If you use an AI coding agent, the README points to a companion repository and a command to install its skills:
npx skills add dinerojs/skillsThe maintainers describe that as teaching an agent "best practices, common pitfalls, and correct usage patterns," which is a reasonable signal that the API has enough sharp edges to be worth documenting for a model.
Where Dinero.js stops: formatting, locale and rounding policy
The most important limitation is stated by the project itself. The documentation's FAQ includes a page titled "Why no currency formatting." Dinero.js does not format money for display. It gives you toDecimal and the underlying value, and the decision about symbols, separators, grouping and locale belongs to your application. If what you actually want is "render this number as euros for a French user," the platform's Intl.NumberFormat already does that, and Dinero.js is an extra layer rather than a replacement.
A second boundary is rounding. Because division does not always land on a whole minor unit, someone has to decide where the remainder goes. Dinero.js exposes allocation-style operations for splitting amounts, but the choice of rounding behaviour is a policy decision your application makes, not one the library makes for you. If you expect the library to pick a sensible default and move on, read the allocation documentation before you ship.
A third boundary is the currency data itself. Currencies come from dinero.js/currencies as explicit objects rather than from the runtime's locale data. That is what makes arbitrary bases possible, and it also means the set of currencies you can use is the set the package defines. If you need a currency that is not there, you are defining it yourself.
Finally, there is the version question. The current line is v2, with v2.0.0 released on 2026-03-02, v2.0.1 on 2026-03-07 and v2.0.2 on 2026-03-13. The README's contributor section still carries a "From v1" list, which tells you the API changed between major versions. If you are migrating an existing v1 codebase, the changelog and release notes are the place to look, not the README, which documents v2 only.
Dinero.js compared with currency.js and decimal.js
These three libraries get grouped together in search results, and they are not the same kind of tool. currency.js is built around formatting and parsing: you hand it a value and it renders it with a symbol and separators, and arithmetic is a convenience on top. Dinero.js inverts that priority. It has no currency formatting at all, by design, and instead makes the amount and the currency explicit so that arithmetic is the primary operation. If your main problem is displaying prices, currency.js is closer to the shape of that problem. If your main problem is that totals drift and splits leave cents behind, Dinero.js is aimed at you.
decimal.js is a different comparison again. It is a general-purpose arbitrary-precision decimal type with no concept of currency, scale or minor units. You would use it to do the arithmetic and then still need to decide what a currency is, how many decimal places it has, and how to represent an amount. Dinero.js is that decision, already made, with decimal arithmetic underneath. The trade-off is scope: decimal.js will do scientific and financial maths that has nothing to do with money, and Dinero.js will not.
Against both, Dinero.js adds two things the others do not carry by default: an immutable functional API where every operation returns a new value, and first-class TypeScript types with full inference. The repository is written in TypeScript, and the README lists type safety as a headline feature. The cost of the functional style is verbosity. add(d1, d2) is longer than d1.add(d2), and a chain of five operations reads as five nested calls rather than a fluent sequence. That is a real ergonomic price for the guarantee that nothing mutates.
Maintenance, licence and upgrade cost
The repository is not archived, and the last push was on 2026-09-15, which is recent. Releases are not frequent, though: the three v2 releases all landed in March 2026, and nothing has shipped since. That pattern suggests a library in a settled state rather than one under rapid change, which is usually what you want from a dependency that touches money, but it also means a bug you hit may sit for a while.
The project is MIT licensed, which is permissive and permits commercial use, modification and redistribution provided the copyright notice and licence text are kept. That is a summary of the licence, not legal advice; read the LICENSE file in the repository if the distinction matters to your organisation.
The upgrade cost is the part to plan for. The move from v1 to v2 changed the API, and the README documents only v2. There is a CHANGELOG.md at the repository root and a release script driven by shipjs, so the changelog is the authoritative record of what moved. Budget for reading it before you upgrade a v1 codebase, because the README will not tell you what changed. On the tooling side, the repository is an npm workspace monorepo managed with turbo, tested with vitest, linted with oxlint and size-checked with size-limit. None of that affects consumers directly, but it does mean the project has automated checks on bundle size and types, which is a reasonable proxy for whether the tree-shaking claim is being maintained.
Editorial conclusion
Adopt Dinero.js when you already know your currency, your rounding rule and your locale, and you want amounts to be integers that survive arithmetic. Skip it when you need a currency-formatting wrapper around Intl.NumberFormat, since the project's own FAQ page is titled "Why no currency formatting". Before committing, check the v2.0.0 release notes for breaking changes from v1, and confirm whether you need the bigint precision mode for the largest amounts your application handles.
Frequently asked questions
What is Dinero.js?
It is a JavaScript and TypeScript library for creating, calculating and formatting monetary values. Amounts are held as integers with an explicit currency object, and every operation returns a new object rather than mutating the existing one.
How do I install Dinero.js?
The README gives npm install dinero.js, or yarn add dinero.js as the alternative. There is no build step or configuration file to set up afterwards.
How do I format currencies in JavaScript with Dinero.js?
Dinero.js does not format currency for display. The documentation's FAQ includes a page titled "Why no currency formatting", and the library gives you toDecimal plus the underlying value so your application can handle symbols, separators and locale itself.
Does Dinero.js work with large amounts?
The README lists pluggable precision: number is the default, and bigint is available for large amounts. The documentation has a guides section covering precision and large numbers.
Does Dinero.js support non-decimal currencies?
Yes. The README states support for any base, including multi-subdivision currencies, which covers currencies that do not use two decimal places.
Is Dinero.js compatible with TypeScript?
Yes. The repository is written in TypeScript and the README lists type safety with full type inference as a feature, alongside a TypeScript-Ready badge.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/dinerojs-dinero-js)