Zum Hauptinhalt springen
tsecurity.de LIVE
Echtzeit-Radar & Feeds
Alle RSS Feeds
👥 Community & Social
Apple iOS & macOSApple arbeitet an einem Fitness-Tracker ohne Display(22.09.2026 um 21:33 Uhr)
Apple iOS & macOSApple stoppt Entwicklung des AirTag-großen KI-Pins(22.09.2026 um 22:22 Uhr)
Apple iOS & macOSApple arbeitet an einem Fitness-Tracker ohne Display(22.09.2026 um 21:33 Uhr)
Apple iOS & macOSApple stoppt Entwicklung des AirTag-großen KI-Pins(22.09.2026 um 22:22 Uhr)
Intelligence View
⚡ tsecurity.de Intelligence

Building a Type-Safe Money Handling Library in TypeScript

Building a Type-Safe Money Handling Library in TypeScript: Lessons from the Financial Technology Trenches After years of wrestling with money-related bugs in financial applications, from rounding errors in e-commerce platforms to…

0
↗ Quelle (dev.to)
Reagiere als Erste:r — dein Feedback zählt!




Building a Type-Safe Money Handling Library in TypeScript: Lessons from the Financial Technology Trenches



After years of wrestling with money-related bugs in financial applications, from rounding errors in e-commerce platforms to currency conversion mishaps in international payment systems, I decided to tackle these challenges head-on. The result is @thesmilingsloth/money-utils, a TypeScript library that brings bank-grade money handling to JavaScript applications. In this post, I'll share the journey, technical decisions, and lessons learned while building it.






The Money Problem in Software Engineering



Money seems simple at first glance—it's just numbers, right? But as Martin Fowler noted in his patterns of enterprise application architecture, money is one of the most complex domains in software engineering. Here's why:






The Floating-Point Trap



JavaScript's number type uses IEEE 754 floating-point arithmetic, which leads to infamous precision issues:




// The classic example
0.1 + 0.2 // => 0.30000000000000004

// But it gets worse
0.1 + 0.2 + 0.3 + 0.4 + 0.5 // => 1.5000000000000002
(0.1 * 100 + 0.2 * 100) / 100 // => 0.30000000000000004






In financial applications, these tiny discrepancies can accumulate into significant errors. Imagine calculating interest rates or processing thousands of transactions—the errors compound quickly.






Real-World Horror Stories



I've seen these issues manifest in production systems:




  1. An e-commerce platform losing thousands of dollars due to rounding errors in bulk discounts

  2. A payment processor having mismatched totals because of currency conversion rounding

  3. An accounting system showing different balances depending on the calculation path






The Solution: A Ground-Up Redesign






1. Decimal Precision Done Right



We chose decimal.js as our foundation after evaluating several options:




import { Money } from "@thesmilingsloth/money-utils";

// Precise calculations, even with complex operations
const principal = new Money("10000.00", "USD");
const interestRate = 0.0525; // 5.25% APR
const years = 5;

const compound = principal.multiply(
Math.pow(1 + interestRate, years)
).round(2);

console.log(compound.toString()); // "$12,900.85"









2. Currency as a First-Class Citizen



Unlike many libraries that treat currency as an afterthought, we made it central to our design:




import { Currency } from "@thesmilingsloth/money-utils";

// Built-in support for major currencies
const usd = Currency.USD;
const eur = Currency.EUR;
const btc = Currency.BTC;

// Custom currency support for tokens or new cryptocurrencies
Currency.register({
name: "Corporate Loyalty Points",
code: "POINTS",
symbol: "",
symbolPosition: "prefix",
decimals: 0,
minorUnits: "1",
thousandsSeparator: ",",
isCrypto: false
});

// Type-safe operations prevent mixing currencies
const dollars = new Money("100.00", "USD");
const euros = new Money("100.00", "EUR");
// This won't compile - TypeScript prevents currency mixing
// const invalid = dollars.add(euros);









3. Smart Allocation with Real-World Examples



Consider splitting a restaurant bill with tax and tip:




const bill = new Money("100.00", "USD");
const tax = bill.multiply(0.08); // 8% tax
const tip = bill.add(tax).multiply(0.20); // 20% tip on subtotal + tax
const total = bill.add(tax).add(tip);

// Split among 3 friends
const shares = total.allocate([1, 1, 1]);
console.log(shares.map(s => s.toString()));
// ["$42.67", "42.67", "42.66"]
// Note: Handles the penny remainder automatically









4. Internationalization Beyond Basic Formatting



Real international applications need more than just symbol placement:




const amount = new Money("1234567.89", "JPY");

// Locale-aware formatting
console.log(amount.toLocaleString("ja-JP")); // "¥1,234,568"
console.log(amount.toLocaleString("en-US")); // "¥1,234,568"
console.log(amount.toLocaleString("de-DE")); // "1.234.568 ¥"

// Custom formatting options
console.log(amount.toLocaleString("en-US", {
style: "currency",
currencyDisplay: "name"
})); // "1,234,568 Japanese yen"









Advanced Features and Edge Cases






1. Handling Cryptocurrency Precision



Cryptocurrencies often require higher precision than traditional currencies:




// Bitcoin with 8 decimal places
const satoshi = new Money("0.00000001", "BTC");
const bitcoin = new Money("1", "BTC");

// Ethereum with 18 decimal places
Currency.register({
name: "Ethereum",
code: "ETH",
symbol: "Ξ",
decimals: 18,
minorUnits: "1000000000000000000",
isCrypto: true
});

const wei = new Money("1", "ETH");
console.log(wei.toString()); // "Ξ0.000000000000000001"









2. Complex Allocation Scenarios



Consider a investment profit distribution with different stakeholder percentages:




const profit = new Money("1000000.00", "USD");
const shares = profit.allocate([
15, // 15% - Founder
25, // 25% - Investors
30, // 30% - Operations
20, // 20% - Development
10 // 10% - Reserve
]);

// Results maintain exact proportions while handling remainders
console.log(shares.map(s => s.toString()));
// [
// "$150,000.00",
// "$250,000.00",
// "$300,000.00",
// "$200,000.00",
// "$100,000.00"
// ]









Performance Optimizations



We've implemented several optimizations:





  1. Memoized Formatting: Caching formatted results for frequently used values


  2. Lazy Evaluation: Deferring expensive operations until needed


  3. Efficient Memory Usage: Structural sharing in immutable operations where possible




// Benchmark results on a MacBook Pro M1:
// 1 million operations
console.time('money-utils');
for (let i = 0; i < 1000000; i++) {
const a = new Money("99.99", "USD");
const b = new Money("49.99", "USD");
const c = a.add(b).multiply(1.08);
}
console.timeEnd('money-utils');
// money-utils: ~450ms









Real-World Integration Examples






1. E-commerce Cart Calculations






class ShoppingCart {
private items: Array<{product: Product, quantity: number}> = [];
private taxRate = 0.08;

addItem(product: Product, quantity: number) {
this.items.push({ product, quantity });
}

calculateTotal(): Money {
const subtotal = this.items.reduce((sum, item) => {
const itemTotal = item.product.price.multiply(item.quantity);
return sum.add(itemTotal);
}, Money.zero("USD"));

const tax = subtotal.multiply(this.taxRate);
return subtotal.add(tax);
}
}









2. Subscription Billing






class SubscriptionBilling {
calculateProration(
monthlyRate: Money,
daysInBillingCycle: number,
daysUsed: number
): Money {
return monthlyRate
.multiply(daysUsed)
.divide(daysInBillingCycle)
.round(2);
}

generateInvoice(subscription: Subscription): Money {
const base = subscription.baseRate;
const usage = this.calculateUsageCharges(subscription);
const discounts = this.applyDiscounts(subscription);

return base
.add(usage)
.subtract(discounts)
.round(2);
}
}









Lessons Learned





  1. Type Safety is Non-Negotiable: TypeScript's type system caught countless potential bugs during development.


  2. Immutability Simplifies Reasoning: Making Money instances immutable eliminated an entire class of bugs.


  3. Testing Edge Cases is Crucial: Our test suite includes over 1000 cases covering various scenarios.


  4. Performance vs. Precision: We chose precision over performance but optimized where possible.






What's Next?



We're working on exciting features:





  • Currency Conversion: Built-in support for currency conversion






Conclusion



Building @thesmilingsloth/money-utils has been a journey through the complexities of financial calculations in software. The library embodies lessons learned from real-world applications and provides a robust foundation for handling monetary calculations in TypeScript applications.



Try it out and let us know what you think! We welcome contributions and feedback on GitHub.






This library is MIT licensed and maintained by Smiling Sloth. Star us on GitHub if you find it useful!

Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Building a Type-Safe Money Handling Library in TypeScript

Thematisch verwandte Begriffe: Building, TypeSafe, Money, Handling · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Zum Aktualisieren ziehen
ZERO-DAY CVE-2026-82000 | Adobe Experience Manager Forms JEE is affected by a Server-Side Request …
Advisory →
TTS Reader • tsecurity.de Voice
tsecurity.de Icon
tsecurity.de App
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag
Themen-Radar & Intelligence Matrix
Echtzeit-Taxonomie nach Angriffsvektoren & Plattformen

tsecurity.de Live Threat Radar

🔴 LIVE RADAR
MONITORING
AKTIV
CVE-DATENBANK
LIVE
🔍
Community Radar & Live Chat
Sentinel Bot online • Live-Stream
Dein Cluster: Security Explorer
Match:
lädt…
Verbindung zum Community-Stream wird aufgebaut...
Bearbeitungsmodus — Senden überschreibt deine Nachricht
Community-Puls — was gerade passiert
lädt…
Aktivitäten deiner Analysten
lädt…
Neues Thema oder Eilmeldung einreichen

Reiche interessante Links, Zero-Days oder Debatten ein. Die Community entscheidet per Upvote über die Veröffentlichung.

Heiß diskutierte Einreichungen
🔖 Gespeicherte Artikel
📂 Keine gespeicherten Artikel vorhanden.
Zurück Ziehen Vor
Links: vorheriger Artikel Rechts: nächster Artikel unten: schließen
News NIS-2 Frühwarnung Tier-1 Intel ⏱️ 3 Min vor 10 Min
Artikeldaten werden geladen...

Zurück: vorheriger Vor: nächster
↗ Original-Quelle
Social Reaktionen Deine Reaktion zählt
Einstufung & Relevanz-Poll 0 Stimmen
In sozialen Netzwerken teilen 1-Klick