Introduction
Working with currency can always be a challenge. To problem lies within the floating numbers (.0212). Typescript like many other programming languages struggle to calculate with those, resulting often in wrong results. Thats why I should never use float numbers in the database and instead, always use only integers. In this article Iβm gonna cover how to fix this problem.
The big.js API
The big.js api targets just this very problem float numbers. It enables me to access a variety of functions, that help me get the numbers right.
I can install it via:
npm install big.jsnpm install @types/big.js --save-devI also linked the official documentation here:
| Source |
|---|
| π big.js website |
big.ts
If I want to customize the big.js api according to my needs, I can do so with creating this file:
src/lib/big.tsHere I can define how my numbers should be, for example:
- It should have 2 decimal places
- Round to nearest, if ties, then round to even numbers (1.65 β 1.6)
import Big from "big.js";
Big.DP = 2;
Big.RM = Big.roundHalfEven;
export const MyBig = Big;currency.ts
The currency.ts defines my functions Iβm gonna need within my application and makes them accessible for all files. It is placed here:
src/utils/currency.tsSome example functions could be:
- Take a Dollar number, turn it into Cents (4,35 β 435)
- Take a Cent number, turn it into Dollars (657 β 6.57)
- Turn a Cent number into a Currency number (320 β $3.20)
import { MyBig } from "@/lib/big";
export const toCent = (amount: number) =>
new MyBig(amount).mul(100).round(2).toNumber();
export const fromCent = (amount: number) =>
new MyBig(amount).div(100).round(2).toNumber();
export const toCurrencyFromCent = (amount: number) =>
new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
}).format(fromCent(amount));Note: The currency.ts makes use of the big.ts file
currency function usage
This chapter will showcase some possible use cases.
upsertTicket
In the database there should always only be integers and never floats. Therefore I need to transform the Dollar number (3.25) into a Cent number (325), before storing it in the database.
// uptaded zod schema
const upsertTicketSchema = z.object({
// ...
bounty: z.coerce.number().positive(),
});
export const upsertTicket = async ( ... ) => {
try {
const data = upsertTicketSchema.parse({
// ...
bounty: formData.get("bounty"),
});
// parse bounty into cents
const dbData = {
...data,
bounty: toCent(data.bounty),
};
// before pushing to the database
await prisma.ticket.upsert({
where: { id: id || "" },
update: dbData,
create: dbData,
});
}
};Input as dollars only
Since the currency is stored in cents (integers) in the database, I will need to convert it back do dollars:
<Input
id="bounty"
name="bounty"
type="number"
step=".01"
defaultValue={
ticket?.bounty ? fromCent(ticket?.bounty) : ""
}
/>Paragraph as dollar with currency $
If I also want to display the currency icon, I need to use this function:
// 499 -> $4.99
<p>{toCurrencyFromCent(ticket.bounty)}</p>Conclusion
Working with floats isnβt easy but thankfully there are people that create incredible APIs for the community, so we have less headache and donβt have to fix it on our own.
| Source |
|---|
| π₯ Road to Next Video > Working with Currencies |