-
Notifications
You must be signed in to change notification settings - Fork 188
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: provide better support for non-decimal currencies #309
Conversation
This pull request is being automatically deployed with Vercel (learn more). 🔍 Inspect: https://vercel.com/dinerojs/dinerojs/G99Pp5thYF5uMaFako93DFaP1fv8 |
This pull request is automatically built and testable in CodeSandbox. To see build info of the built libraries, click here or the icon next to each commit SHA. Latest deployment of this branch, based on commit 2bf6376:
|
ecf9d4d
to
6b8c3b1
Compare
6b8c3b1
to
c430bee
Compare
737a0d8
to
6173166
Compare
177c955
to
3f25995
Compare
toUnit
with toUnits
Co-authored-by: John Hooks <bitmachina@outlook.com>
Co-authored-by: John Hooks <bitmachina@outlook.com>
Co-authored-by: John Hooks <bitmachina@outlook.com>
Co-authored-by: John Hooks <bitmachina@outlook.com>
Co-authored-by: John Hooks <bitmachina@outlook.com>
400c2f5
to
2bf6376
Compare
@johnhooks That works for me, and makes the build slightly smaller by not setting default values. Check 2bf6376 and let me know what you think :) |
Looks great, I'd say it's ready! |
This PR changes the way Dinero.js does formatting, providing better support for non-decimal currencies and large integers. Many changes are going in this PR, as this touches several concepts of the library.
Currencies now accept multi-bases
Currencies can have multiple bases. It's the case for the pre-decimal pound sterling, the livre tournois of the French Old Regime, or the Harry Potter wizarding currency of Great Britain. Users creating custom currencies (e.g., for games) may also want to create such currencies.
Until now, Dinero.js allowed you to support such currencies by providing the number of units of the smallest subdivision to the biggest (e.g., 240 pence in a pound) as the
base
. It meant thattoUnit
could only return a double representation of the amount, and that you'd have to write a lot of logic to properly format it.Accepting multiple-bases lets users express this complexity and enables better formatting in the new
toUnits
function.toUnit
is replaced withtoUnits
The
toUnit
function currently returns a double, which is problematic at several levels:number
s, so this operation can't work well with them.The decimal representation (e.g., 10.5) is prevalent in systems using a decimal currency, but this is only a human representation, and only matters when you're displaying an amount on your site or app. Programming-wise, this representation isn't particularly helpful, and it's even limiting.
This PR removes
toUnit
and replaces it withtoUnits
, which returns each subdivision as an integer (anumber
, abigint
, aBig
, depending on what you use as the amount type), in an array.This accounts for decimal and non-decimal currencies, without forcing the "human" representation of one over the other. Thanks to multi-bases, the function handles the heavy lifting of distributing an amount into the right amount of each of its subdivision (e.g., 267 pence is 1 pound, 2 shillings and 3 pence,
toUnits
returns[1, 2, 3]
). SincetoUnits
is now used bytoFormat
under the hood (instead oftoUnit
), it makes formatting even easier.toFormat
is replaced withtoDecimal
Until now,
toFormat
was the catch-all formatting function for any formatting need. It was also "only" a wrapper aroundtoUnit
, exposing the right information in a transformer function for users to format and display objects.An intermediary design was to expose both the data from
toUnits
and adecimal
representation intoFormat
. But ultimately, there's no point in having a single function that exposes everything: it's computationally more expensive and it does too many things.Instead, this PR introduces
toDecimal
, a formatter function that returns a stringified decimal representation. This is more reliable because of the string format which prevents the system from converting it to an inaccurate binary representation.Another benefit is that the string representation retains the exponent, meaning that $10.50, which used to be returned as
10.5
will now be returned as"10.50"
. If users need this as a double, despite the potential lack of accuracy (e.g., to manipulate it or use it with the Intl API), they can easily cast it withNumber
orparseFloat
, but that's their responsibility.toDecimal
is only meant to be used with decimal, single-base objects. For multi-base or non-decimal needs,toUnits
is recommended.toUnits
andtoDecimal
take a transformer as its second parameterThis makes it easier for users to customize the output based on the exposed
value
:toUnits
toDecimal
PR notes
BREAKING CHANGE: the
toUnit
and thetoFormat
functions were removed.fix #294