How To Build A Money Data Type In JavaScript
Tags: webdev, programming, node, softwaredevelopment
Published: 2023-05-13 05:38:40

---
title: How To Build A Money Data Type In JavaScript
published: true
tags: webdevelopment,programming,nodejs,softwaredevelopment
canonical_url: https://fagnerbrack.com/how-to-build-a-money-data-type-in-javascript-7b622beabe00
---

### How To Build A Money Data Type In JavaScript 🔊

#### An alternative to the floating point trap

![](https://cdn-images-1.medium.com/max/1024/1*7KJLRKjFcbRSk-qjhad7JA.jpeg)<figcaption>The picture of a massive flame from a <a href="https://en.wikipedia.org/wiki/Fire_breathing">Fire Breathing</a> act. The background is dark. The fire comes from the right, a hidden person outside the screen executes the technique (<a href="https://commons.wikimedia.org/wiki/File:Flame_of_fire.jpg">source</a>)</figcaption>

<iframe src="https://cdn.embedly.com/widgets/media.html?url=https%3A%2F%2Fplay.ht%2Farticles%2F7b622beabe00&amp;src=https%3A%2F%2Fplay.ht%2Fembed%2F%3Farticle_url%3Dhttps%3A%2F%2Fmedium.com%2F_p%2Fhow-to-build-a-money-data-type-in-javascript-7b622beabe00&amp;type=text%2Fhtml&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;schema=play" width="700" height="185" frameborder="0" scrolling="no"><a href="https://medium.com/media/c6a297a02739ae631dd69b453cf0602c/href">https://medium.com/media/c6a297a02739ae631dd69b453cf0602c/href</a></iframe>

Last time I wrote a [step-by-step example](https://dev.to/fagnerbrack/the-missing-practical-step-by-step-tdd-2ap9-temp-slug-3121368) of how to apply [Inside Out Test-Driven Development](https://8thlight.com/blog/georgina-mcfadyen/2016/06/27/inside-out-tdd-vs-outside-in.html) to a problem using JavaScript. That post used the Number type to represent dollars.

According to the [JavaScript specification](https://es5.github.io/#x8.5), the Number type is a “[double-precision 64-bit binary format IEEE 754](https://en.wikipedia.org/wiki/Double-precision_floating-point_format#IEEE_754_double-precision_binary_floating-point_format:_binary64)” value. You shouldn’t use implementations of IEEE 754 to represent any data where you need to have precision. Money is one of them.

There is [too](http://wiki.c2.com/?FloatingPointCurrency) much [content](https://husobee.github.io/money/float/2016/09/23/never-use-floats-for-currency.html) out [there](https://stackoverflow.com/questions/3730019/why-not-use-double-or-float-to-represent-currency) about [this subject](https://spin.atomicobject.com/2014/08/14/currency-rounding-errors/). Therefore, this post shows, through coding examples, how you can create a model that can handle money types correctly

> You shouldn't use the "Number" type in JavaScript to represent Money

Jack, The Moneylender, started to calculate some loans using the function from the [previous post](https://dev.to/fagnerbrack/the-missing-practical-step-by-step-tdd-2ap9-temp-slug-3121368). At some point, he tried to calculate the loan amount of "$2585." The result was "$52.73" followed by "999999999999."

Jack is not happy about this. Five years ago, his friend worked as an accountant for a Mafia queen. One day, she spotted a weird fractional number from an account and got suspicious.

She fired him. Like… with actual fire!

All right, Jack is not working for the Mafia right now. However, he doesn’t like the fact a calculation might yield the incorrect result in certain circumstances.

You need to fix it.

> Jack doesn't like fire

In the book "Patterns of Enterprise Application Architecture," Martin Fowler [provides a solution](https://martinfowler.com/eaaCatalog/money.html) to the representation of monetary values. He suggests you can create a model that [affords](https://hackernoon.com/affordance-in-software-design-12cc0d9d2721) some arithmetic operations. However, the code runs the calculations on top of an "amount," which is an internal non-fractional property that is not affected by floating point issues.

You can decouple the visual representation from the logic and run all the math in cents.

If you represent the cents as non-fractional Numbers, you don't need to worry about floating point issues. Later, you can convert the Number into a String and decide where to put the [decimal separator](https://en.wikipedia.org/wiki/Decimal_separator) according to the currency you want to output.

<iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/89727368eac16e0d417116e5d1f2eb32/href">https://medium.com/media/89727368eac16e0d417116e5d1f2eb32/href</a></iframe>

Given this is a general programming concern and not a very specific [Problem Domain](https://en.wikipedia.org/wiki/Problem_domain), the programming language should at least provide a solution out of the box.

Unfortunately, JavaScript doesn’t have a decimal or a money type, and I don’t recommend you to spend the time to [reinvent](https://en.wikipedia.org/wiki/Not_invented_here) it. There are some libraries out there such as [dinero.js](https://github.com/sarahdayan/dinero.js) that are worth investigating.

For this post, though, let’s create a Money type from scratch.

The only operations that are necessary, according to the "[interest to pay for dollars](https://github.com/FagnerMartinsBrack/jack-the-moneylender/blob/d0de7c4f03fc3c85af62a392a747a9bff9f6f0c7/index.html#L9-L17)" function, is the subtraction, multiplication and the "greater than." There’s no need to spend the time to develop [affordances](https://hackernoon.com/affordance-in-software-design-12cc0d9d2721) you [don’t need right now](https://en.wikipedia.org/wiki/You_aren%27t_gonna_need_it).

<iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/af65cf7007cd95691a9d3ac39ac2bfd5/href">https://medium.com/media/af65cf7007cd95691a9d3ac39ac2bfd5/href</a></iframe>

The constructor of the new model accepts a String with a dollar sign ("$1.00"). There’s no need to support multiple currencies at this point, so it's safe to use that notation.

Also, the new model requires that consumers always specify two decimal digits ".00," even when the value is round like "$5.00," instead of omitting the digits like "$1." The logic is more straightforward that way. It's easier to reason about the problem.

```
Money('$0.01');
Money('$0.10');
Money('$1.00');
Money('$10.00');
Money('$12.45');
```

The minus operation subtracts the value in cents. Later, it generates the visual representation and prefix with the negative sign, if necessary.

To produce the visual representation, you put the decimal point on the second to last digit. If the decimal point location ends up before the first digit, fill the missing characters with zeroes.

<iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b946fd446a90e119d5119f5582c818ed/href">https://medium.com/media/b946fd446a90e119d5119f5582c818ed/href</a></iframe>

The multiplication is trickier than the subtraction. Would it make sense to multiply dollars to cents? Maybe. Let's try.

To solve the [interest problem](https://dev.to/fagnerbrack/the-missing-practical-step-by-step-tdd-2ap9-temp-slug-3121368) for Jack, you need to run calculations like $1.00 multiplied by $0.09. Therefore, it seems reasonable to use other dollar values instead of a Number in the multiplication factors.

Since you're multiplying two dollar values as cents, if you multiply $2.00 by $2.00, you get 40000 cents. The representation of that is $400.00, but the result should be $4.00.

If you divide the result of the calculation by 100, you get the correct output of 400 cents. However, you can avoid the mathematical division by slicing the last 2 digits out of the multiplication result.

<iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e1a6847bb50d7f9476f35e7a7141a224/href">https://medium.com/media/e1a6847bb50d7f9476f35e7a7141a224/href</a></iframe>

Of course, both solutions come at the expense of losing the precision beyond 2 decimal digits.

<iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e18c985798f1fe7a2daee1faa2b608f6/href">https://medium.com/media/e18c985798f1fe7a2daee1faa2b608f6/href</a></iframe>

You can see the final result, without further optimization, in [a commit](https://github.com/FagnerMartinsBrack/jack-the-moneylender/commit/7f578977fc43d730ea7ef08d2ba8bfdebb9b9f5b) to the "Jack, The Moneylender" repository, including [the tests for the new model](https://github.com/FagnerMartinsBrack/jack-the-moneylender/blob/7f578977fc43d730ea7ef08d2ba8bfdebb9b9f5b/dollar.html#L10-L115).

I used TDD to produce this code, just like I did with the [first deliverable](https://dev.to/fagnerbrack/the-missing-practical-step-by-step-tdd-2ap9-temp-slug-3121368) for Jack. However, this post is not to show you how to do TDD; it’s to understand how you can work around the lack of precision for floating point numbers.

> There are many ways to represent money. One of them is to represent as cents.

Nothing prevents you from increasing the precision and scaling above cents, such as to support the [Mill currency](https://en.wikipedia.org/wiki/Mill_(currency)) or [fractions of Bitcoin (satoshis)](https://en.wikipedia.org/wiki/Bitcoin#Units). To do that and keep backward compatibility, assume the missing digits have a value of zero. If you want to downscale from satoshis to cents, the code won’t break either; only you’ll lose precision beyond 2 decimal digits.

Floating point numbers are a trap. They fit the problem correctly; until they don't. At that point, it will probably be too late to make any change.

Don’t use the fractional representation of the JavaScript Number type to represent money. In fact, don't use floating points for anything that require precision.

You don’t need to be involved with the Mafia for something terrible to happen. If you don't care about software design, then someone might have to put down the fire later.

It can even be yourself.

Thanks for reading. If you have some feedback, reach out to me on [Twitter](https://twitter.com/FagnerBrack), [Facebook](https://www.facebook.com/fagner.brack) or [Github](http://github.com/FagnerMartinsBrack).

Thanks to [Jon Eaves](https://joneaves.wordpress.com/), **Stephan Classen** and [Jay Bazuzi](http://jay.bazuzi.com/) for their insightful inputs to this post.

* * *