Careeroza
Real World Example
Bank Transfer With Typed Errors
A banking or UPI app must tell the user exactly why a transfer failed: wrong PIN, low balance or daily limit. Expected failures are Results; a broken database connection is an exception that bubbles up to a global handler which logs it and returns HTTP 500.
Example
type TransferError =
| { code: "INSUFFICIENT_FUNDS"; balance: number }
| { code: "DAILY_LIMIT"; remaining: number }
| { code: "SAME_ACCOUNT" };
type Result<T, E> = { ok: true; value: T } | { ok: false; error: E };
class DatabaseError extends Error { name = "DatabaseError"; }
const balances: Record<string, number> = { A1: 5000, B2: 100 };
const DAILY_LIMIT = 10000;
let sentToday = 8000;
let dbUp = true;
function transfer(from: string, to: string, amount: number): Result<string, TransferError> {
if (!dbUp) throw new DatabaseError("connection refused");
if (from === to) return { ok: false, error: { code: "SAME_ACCOUNT" } };
const bal = balances[from] ?? 0;
if (amount > bal) return { ok: false, error: { code: "INSUFFICIENT_FUNDS", balance: bal } };
if (sentToday + amount > DAILY_LIMIT) return { ok: false, error: { code: "DAILY_LIMIT", remaining: DAILY_LIMIT - sentToday } };
balances[from] = bal - amount;
balances[to] = (balances[to] ?? 0) + amount;
sentToday += amount;
return { ok: true, value: "TXN" + (1000 + sentToday) };
}
function message(e: TransferError): string {
switch (e.code) {
case "INSUFFICIENT_FUNDS": return `Low balance (Rs. ${e.balance})`;
case "DAILY_LIMIT": return `Daily limit reached, Rs. ${e.remaining} left today`;
case "SAME_ACCOUNT": return "Cannot send to the same account";
}
}
function handle(from: string, to: string, amount: number): void {
try {
const r = transfer(from, to, amount);
console.log(r.ok ? "Success " + r.value : "Failed: " + message(r.error));
} catch (e) {
console.log("HTTP 500, logged:", e instanceof Error ? e.name + ": " + e.message : e);
}
}
handle("A1", "B2", 1500);
handle("B2", "A1", 5000);
handle("A1", "B2", 1000);
handle("A1", "A1", 10);
dbUp = false;
handle("A1", "B2", 10);Output
Success TXN10500 Failed: Low balance (Rs. 1600) Failed: Daily limit reached, Rs. 500 left today Failed: Cannot send to the same account HTTP 500, logged: DatabaseError: connection refused