Convert a number to a proper amount in Javascript.
Tags: javascript
Published: 2023-05-08 11:12:45

---
title: Convert a number to a proper amount in Javascript.
published: true
date: 2022-10-17 00:00:00 UTC
tags: Javascript
canonical_url: https://blog.melvinvmegen.com/snippets/amount
---
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/htyssimcpkfo07vwcrjw.png)
```js
const amount = (value, currency = "EUR", long) => {
  return (
    (Number(value) || 0)
      .toFixed(long ? 2 : 0)
      .replace(/-/g, "-\u00a0")
      .replace(/(\d)(?=(\d{3})+(\.|$))/g, "$1\u00a0")
      .replace(".", ",") +
    (currency
      ? "\u00a0" +
        ({
          EUR: "€",
          USD: "$",
          GBP: "£",
        }[currency] || currency)
      : "")
  );
};
```

## Context

In development we often have to manipulate numbers that need to be represented as amounts to our users. Unfortunately, in javascript there is no native way of doing it.

> Well actually there is a [native function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat) which as recently been supported in Node 19 thanks to a bump to the latest version of the V8 engine but as we wont be able to use it in production for a while consider this as still relevant :)(Node 19 is a odd numbered release meaning it's not an **LTS version**, unless it's backported of course).

The **amount() function** allows us to do it!

## Usage

```js
amount(200); // 200 €
amount(200, "$"); // 200 $
amount(200, "GBP"); // 200 £
amount(200, "GBP", true); // 200,00 £
```

## Explanation

The **amount() function** takes 3 arguments, a number, a currency with a default value of **EUR**. And last but not least, a boolean conditioning the result as an amount with 2 decimal places or round.

The **amount() function** then proceeds as follow:

- The first parameters is either parsed or converted into a Number type thanks to the [Number() function] which is almost equivalent to [unary plus (+x)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Unary_plus) but allows in my opinion for a better understanding. 
Beware of [parseInt()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt) which converts empty strings to NaN. If you're looking for a [conversion table](https://i.stack.imgur.com/LLrgj.png).

```js
let value;
value = Number(false) || 0; // 0
value = Number("test") || 0; // 0
value = Number("-1000") || 0; // -1000
```

- The value is then converted to a string with the given rounding.
```js
let stringified_value = (Number(1000) || 0).toFixed(0); // '1000'
stringified_value = (Number(1000) || 0).toFixed(2); // '1000.00'
```
- In case of a negative number, spaces out the number from the minus in order to properly format it down the line.

```js
const spaced_out_neg_value = stringified_value.replace(/-/g, "-\u00a0"); // '- 1000.00'
```

- Properly formatting the value spacing out every third character.

```js
// Space out every third character
const formatted_neg_value = spaced_out_neg_value.replace(
  /(\d)(?=(\d{3})+(\.|$))/g,
  "$1\u00a0"
); // '- 1 000.00'
```

- Replaces the **dot** by a **comma** the suffix the value with the currency given as second parameter.

```js
const comma_formatted_neg_value = formatted_neg_value.replace(".", ","); // '- 1 000,00'

const currency = "EUR";
const amount =
  comma_formatted_neg_value +
  ("\u00a0" +
    ({
      EUR: "€",
      USD: "$",
      GBP: "£",
    }[currency] || currency)); // '- 1 000,00 €'
```

**What if we pass an unreferenced currency? Or if we pass null by accident? Let's try to isolate this behaviour in an independent function.**

```js
const add_currency = (value, currency) => {
  return (
    value +
    (currency
      ? "\u00a0" +
        ({
          EUR: "€",
          USD: "$",
          GBP: "£",
        }[currency] || currency)
      : "")
  );
};

add_currency("1 000,00", "USD"); // '1 000,00 $'
add_currency("1 000,00", "¥"); // '1 000,00 ¥'
add_currency("1 000,00", "curry"); // '1 000,00 curry'
add_currency("1 000,00", null); // '1 000,00'
```

As you probably noticed any value can be passed as second parameter but for optimal use it should be added to the values currently supported **({EUR:"€", USD:"$", GBP:"£"})**

## Conclusion

The final snippet in a concise expression:

```js
const amount = (value, currency = "€", long) => {
  return (
    (Number(value) || 0)
      .toFixed(long ? 2 : 0)
      .replace(/-/g, "-\u00a0")
      .replace(/(\d)(?=(\d{3})+(\.|$))/g, "$1\u00a0")
      .replace(".", ",") +
    (currency
      ? "\u00a0" +
        ({
          EUR: "€",
          USD: "$",
          GBP: "£",
        }[currency] || currency)
      : "")
  );
};
```