Falsehoods Programmers Believe About Money

A presentation at NodeConf Remote in October 2021 in by Sarah Dayan

Slide 1

Slide 1

Falsehoods Programmers Believe About Money Sarah Dayan NodeConf Remote 2021

Slide 2

Slide 2

Slide 3

Slide 3

You can safely store money as a fractional value

Slide 4

Slide 4

const cart = [ { name: ‘Mass Effect: Legendary Edition’, platform: ‘Xbox One’, price: 69.99, }, { name: ‘The Legend of Zelda: Breath of the Wild’, platform: ‘Nintendo Switch’, price: 51.91, } ];

Slide 5

Slide 5

cart.reduce((acc, { price }) => acc + price, 0); // 121.89999999999999 😧

Slide 6

Slide 6

Slide 7

Slide 7

‣ ‣ number (doubles) bigint (arbitrary precision integers)

Slide 8

Slide 8

dinero({ amount: 6999, currency: USD });

Slide 9

Slide 9

$69.99 ¢6999

Slide 10

Slide 10

type Money<TAmount> = { amount: TAmount; currency: Currency<TAmount>; // … }

Slide 11

Slide 11

All currencies are decimal and split into 100 sub-units

Slide 12

Slide 12

Slide 13

Slide 13

x = 100x / 100

Slide 14

Slide 14

function toMajorUnit(minorUnitAmount) { return minorUnitAmount / 100; }

Slide 15

Slide 15

Slide 16

Slide 16

const USD = { code: ‘USD’, base: 10, exponent: 2, }; // Represents USD 10.00 dinero({ amount: 1000, currency: USD });

Slide 17

Slide 17

// Iraqi dinar const IQD = { code: ‘IQD’, base: 10, exponent: 3, }; // Represents IQD 1.000 dinero({ amount: 1000, currency: IQD });

Slide 18

Slide 18

// Japanese yen const JPY = { code: ‘JPY’, base: 10, exponent: 0, }; // Represents JPY 1000 dinero({ amount: 1000, currency: JPY });

Slide 19

Slide 19

// Mauritanian ouguiya const MRU = { code: ‘MRU’, base: 5, exponent: 1, }; // Represents 2 ouguiyas and 3 khoums dinero({ amount: 13, currency: MRU });

Slide 20

Slide 20

Currencies can’t be subdivided further than their sub-unit

Slide 21

Slide 21

Slide 22

Slide 22

€19.95 + 5.5% VAT €21.04725

Slide 23

Slide 23

const EUR = { code: ‘USD’, base: 10, exponent: 3, }; // Represents EUR 1.131 const diesel = dinero({ amount: 1131, currency: EUR });

Slide 24

Slide 24

// Represents EUR 1.131 dinero({ amount: 1131, currency: EUR, scale: 3 });

Slide 25

Slide 25

const diesel = dinero({ amount: 1131, currency: EUR, scale: 3 }); const fullTank = multiply(diesel, 50); const coffee = dinero({ amount: 99, currency: EUR }); // Amount 57540 and scale 3 (aka EUR 57.540) const total = add(fullTank, coffee);

Slide 26

Slide 26

All currencies have a single subdivision level

Slide 27

Slide 27

Slide 28

Slide 28

Slide 29

Slide 29

// Pre-decimal Great Britain pound sterling const GBP = { code: ‘GBP’, base: [20, 12], exponent: 1, }; // 267 pence, or 1 pound, 2 shillings and 3 pence const d = dinero({ amount: 267, currency: GBP }); toUnits(d); // [1, 2, 3]

Slide 30

Slide 30

Splitting money is as simple as dividing it

Slide 31

Slide 31

const purchase = { title: ‘Microsoft Xbox Series S’, price: 369.99, };

Slide 32

Slide 32

const length = 2; Array.from({ length }).map(() => purchase.price / length); // [184.995, 184.995]

Slide 33

Slide 33

Array.from({ length: count }).map( () => Math.round((purchase.price / count) * 100) / 100 ); // [185, 185]

Slide 34

Slide 34

const purchase = { title: ‘Microsoft Xbox Series S’, price: dinero({ amount: 36999, currency: USD }), }; const [d1, d2] = allocate(purchase.price, [50, 50]); d1; // a Dinero object with amount 18500 d2; // a Dinero object with amount 18499

Slide 35

Slide 35

You’ll never need to represent very large amounts

Slide 36

Slide 36

296000000000000

Slide 37

Slide 37

296000000000000 9000000000000000

Slide 38

Slide 38

29600000000000000 9000000000000000

Slide 39

Slide 39

Slide 40

Slide 40

const dineroBigint = createDinero({ calculator: { add: (a, b) => a + b, // … }, });

Slide 41

Slide 41

const dineroBigJs = createDinero({ calculator: { add: (a, b) => a.plus(b), // … }, });

Slide 42

Slide 42

const USD = { code: ‘USD’, base: 10n, exponent: 2n, }; dineroBigint({ amount: 500n, currency: USD });

Slide 43

Slide 43

So, is JavaScript safe to manipulate money?

Slide 44

Slide 44

Thank you! ff @frontstu _io