Learning from the Mistakes of a v1
@frontstuff_io


Sarah Dayan
Software Engineer, Algolia


const price = Dinero({
amount: 5000,
currency: 'EUR'
});
const tip = price.percentage(20);
const fullPrice = price.add(tip);
fullPrice.toFormat(); // "€60.00"
@frontstuff_io
years
2
commits
400
releases
29



@frontstuff_io
A v2 usually marks
a turning point.
@frontstuff_io

It uses numbers to represent amounts
🔢
@frontstuff_io



@frontstuff_io
const price = Dinero({
amount: 5000,
currency: 'EUR'
});
.1 + .2;
// 0.30000000000000004
(1 + 2) / 10
// 0.3
@frontstuff_io
@frontstuff_io
const price = Dinero({
// 5000 cents, or 50 euros
amount: 5000,
currency: 'EUR'
});
Number.MAX_SAFE_INTEGER;
// 9007199254740991
Number.MIN_SAFE_INTEGER;
// -9007199254740991
@frontstuff_io
@frontstuff_io
Enter bigints.
const calculator = {
add(a, b) {
return a + b;
},
subtract(a, b) {
return a - b;
},
// ...
};
@frontstuff_io
import { Decimal } from 'decimal.js';
const bigDinero = createDinero({
calculator: {
add: Decimal.add,
subtract: Decimal.sub,
// ...
},
});
const price = bigDinero({
amount: new Decimal(Number.MAX_SAFE_INTEGER),
currency: 'EUR',
});
@frontstuff_io
It doesn't handle different exponents
💰
@frontstuff_io



@frontstuff_io
1 euro = 100 cents
1 x 10^2 = 100
const price = Dinero({
amount: 5000,
currency: 'EUR',
});
price.toFormat(); // "€50.00"
@frontstuff_io
@frontstuff_io

const price = Dinero({
amount: 1000,
currency: 'IQD',
precision: 3,
});
@frontstuff_io
const IQD = {
code: 'IQD',
base: 10,
exponent: 3,
};
const price = Dinero({
amount: 1000,
currency: IQD,
});
@frontstuff_io
It expects a REST API for conversions
🔄
@frontstuff_io



const options = {
endpoint: 'https://api/?base={{from}}',
propertyPath: 'data.rates.{{to}}',
headers: {
'user-key': 'xxxxxxxxx',
},
roundingMode: 'HALF_UP',
};
Dinero({
amount: 5000,
currency: 'EUR',
}).convert('XBT', options);
@frontstuff_io
const price = Dinero({
amount: 5000,
currency: 'EUR',
});
price.convert('XBT');
@frontstuff_io
const rates = new Promise((resolve) =>
resolve({
XBT: 0.00012,
})
);
Dinero({ amount: 5000 })
.convert(EUR, { rates });
@frontstuff_io
const rates = {
rates: {
XBT: 0.00012,
},
};
Dinero({
amount: 5000,
currency: 'EUR',
}).convert('XBT', {
endpoint: new Promise((resolve) =>
resolve(rates)
),
});
@frontstuff_io
It relies on the ECMAScript I18n API
🌎
@frontstuff_io



const amount = 5;
amount.toLocaleString('en-GB', {
style: 'currency',
currency: 'EUR',
});
// "€5.00"
@frontstuff_io
const options = {
style: 'currency',
currency: 'EUR',
};
amount.toLocaleString('en-GB', options);
// "€5.00"
amount.toLocaleString('de-DE', options);
// "5,00 €"
@frontstuff_io
const price = Dinero({
amount: 500,
currency: 'EUR',
}).setLocale('en-GB');
price.toFormat();
// "€5.00"
@frontstuff_io
@frontstuff_io
Tight coupling
@frontstuff_io
Lack of flexibility
@frontstuff_io
Inconsistent
implementation
const price = Dinero({
amount: 500,
currency: EUR,
});
price.toFormat(
({ amount, currency }) =>
`${currency.code} ${amount}`,
{
digits: 2,
roundingMode: Math.round,
}
);
// "EUR 5"
@frontstuff_io
function i18n({ amount, currency }) {
return amount.toLocaleString('en-GB', {
style: 'currency',
currency: currency.code,
});
}
price.toFormat(i18n, {
digits: 2,
roundingMode: Math.round,
});
// "€5.00"
@frontstuff_io
const currencySymbols = {
EUR: '€',
USD: '$',
// ...
};
function manualI18n({ amount, currency }) {
const { code } = currency;
const symbol = currencySymbols[code] || code;
return `${symbol}${amount.toFixed(2)}`;
}
price.toFormat(manualI18n, {
digits: 2,
roundingMode: Math.round,
});
// "€5.00"
@frontstuff_io
You can't tree-shake it
🌳
@frontstuff_io




const price = Dinero({
amount: 500,
currency: 'EUR',
});
price.add(price).multiply(4);
@frontstuff_io
const price = Dinero({
amount: 500,
currency: 'EUR',
});
multiply(add(price, price), 4);
@frontstuff_io
@frontstuff_io

It's written
in JavaScript
🐞
@frontstuff_io



@frontstuff_io
Maintaining types
by hand doesn't scale.
And it's a pain.
@frontstuff_io
Static typing is extremely helpful.
@frontstuff_io
🐦
TypeScript hits two birds with one stone.
@frontstuff_io
What happened?
@frontstuff_io
First library



@frontstuff_io
No real-world experience



@frontstuff_io
Many assumptions



@frontstuff_io
Scalability
Flexibility
Agnosticism
DX
@frontstuff_io



Links
Why Javascript Numbers Are Weird (And How to Fix It)
youtu.be/Wq2AqONg7rs
Dinero.js on GitHub
github.com/dinerojs

Sarah Dayan
Software Engineer, Algolia
Thank you!

Learning from the Mistakes of a v1
By Sarah Dayan
Learning from the Mistakes of a v1
- 472