import {Option, fromNullable, matchW} from 'fp-ts/lib/Option'; // keep it simple export type Account = string; export interface Bank { balance: (account: Account) => Promise>; /// Deposit amount into account /// /// This function increases the balance of the given account by the /// specified amount. It's a `void` function hence implicitly /// stateful: It's expected to change some internal state of the /// implementing class. /// /// @param account The account to deposit into /// @param amt The amount to deposit deposit: (account: Account, amt: number) => Promise; withdraw: (account: Account, amt: number) => Promise; } export class SimpleBank implements Bank { private accounts: Map; constructor(accounts: Map) { // clone the content of the map this.accounts = new Map(accounts); } balance(account: Account): Promise> { return Promise.resolve(fromNullable(this.accounts.get(account))); } deposit(account: Account, amt: number): Promise { const current = fromNullable(this.accounts.get(account)); matchW( () => { throw new Error(`Unknown account ${account}`); }, (bal: number) => { this.accounts.set(account, bal + amt); }, )(current); return Promise.resolve(); } withdraw(account: Account, amt: number): Promise { const current = fromNullable(this.accounts.get(account)); matchW( () => { throw new Error(`Unknown account ${account}`); }, (bal: number) => { this.accounts.set(account, bal - amt); }, )(current); return Promise.resolve(); } } export type Operation = GetBalance | Withdraw | Deposit; export type GetBalance = {op: 'GetBalance'; account: Account}; export type Withdraw = {op: 'Withdraw'; account: Account; amount: number}; export type Deposit = {op: 'Deposit'; account: Account; amount: number};