A TypeScript library of 15 financial calculators covering interest, loans, investments, taxes, and business analysis. Zero dependencies, fully typed, with strict mode enabled.
npm install calculatorsOr clone and build from source:
git clone https://github.com/your-username/Calculators.git
cd Calculators
npm install
npm run buildimport { Mortgage, CompoundInterest, Compound } from "calculators";
// Calculate monthly mortgage payment
const mortgage = new Mortgage(350000, 70000, 6.5, 30);
const result = mortgage.calculate();
console.log(result.monthlyPayment); // 1770.27
// Calculate compound interest
const ci = new CompoundInterest(10000, 5, 10, Compound.Monthly);
console.log(ci.calculate()); // 16470.09Calculates simple interest using A = P(1 + rt).
import { SimpleInterest } from "calculators";
const si = new SimpleInterest(1000, 5, 3);
// constructor(principal, ratePercentage, years)
console.log(si.calculate()); // 1150.00| Parameter | Type | Description |
|---|---|---|
principal |
number |
Initial amount (must be > 0) |
ratePercentage |
number |
Annual rate as a percentage, 0-100 |
years |
number |
Time period in years (>= 0) |
Returns: number — the total amount (principal + interest).
Calculates compound interest using A = P(1 + r/n)^(nt).
import { CompoundInterest, Compound } from "calculators";
const ci = new CompoundInterest(5000, 8, 5, Compound.Quarterly);
console.log(ci.calculate()); // 7429.74| Parameter | Type | Description |
|---|---|---|
principal |
number |
Initial amount (must be > 0) |
ratePercentage |
number |
Annual rate, 0-100 |
years |
number |
Time period (must be > 0) |
compound |
Compound |
Compound.Monthly, Compound.Quarterly, or Compound.Annually |
Returns: number — the total amount after compounding.
Estimates the time required to double an investment.
import { RuleOf72 } from "calculators";
const r72 = new RuleOf72(8);
const result = r72.calculate();
console.log(result.estimatedYears); // 9
console.log(result.exactYears); // 9.01| Parameter | Type | Description |
|---|---|---|
ratePercentage |
number |
Annual rate, 0 < rate < 100 |
Returns: RuleOf72Result
| Field | Type | Description |
|---|---|---|
estimatedYears |
number |
72 / rate (rounded to 2 decimals) |
exactYears |
number |
ln(2) / ln(1 + rate/100) |
Calculates monthly and yearly mortgage payments.
import { Mortgage } from "calculators";
const m = new Mortgage(300000, 60000, 6, 30);
// constructor(amount, downPayment, ratePercentage, years)
const result = m.calculate();
console.log(result.monthlyPayment); // 1438.92
console.log(result.yearlyPayment); // 17267.04
console.log(result.totalNumberOfPayments); // 360| Parameter | Type | Description |
|---|---|---|
amount |
number |
Total property price (must be > 0) |
downPayment |
number |
Down payment (>= 0, must be < amount) |
ratePercentage |
number |
Annual rate, 0 < rate < 100 |
years |
number |
Loan term as a positive integer |
Returns: MortgageResult
| Field | Type | Description |
|---|---|---|
monthlyPayment |
number |
Monthly payment amount |
yearlyPayment |
number |
Annual payment amount |
totalNumberOfPayments |
number |
Total number of monthly payments |
Generates a full amortization schedule with principal/interest breakdown per payment.
import { LoanAmortization } from "calculators";
const la = new LoanAmortization(200000, 6, 30);
const result = la.calculate();
console.log(result.monthlyPayment); // 1199.10
console.log(result.totalInterest); // 231677.04
console.log(result.schedule[0]);
// { payment: 1, principal: 199.10, interest: 1000.00, remainingBalance: 199800.90 }| Parameter | Type | Description |
|---|---|---|
loanAmount |
number |
Loan principal (must be > 0) |
ratePercentage |
number |
Annual rate, 0 < rate < 100 |
years |
number |
Loan term as a positive integer (max 100) |
Returns: AmortizationResult
| Field | Type | Description |
|---|---|---|
monthlyPayment |
number |
Fixed monthly payment |
totalPayments |
number |
Total number of payments |
totalInterest |
number |
Total interest paid over the life of the loan |
schedule |
AmortizationEntry[] |
Per-payment breakdown |
Each AmortizationEntry:
| Field | Type | Description |
|---|---|---|
payment |
number |
Payment number (1-indexed) |
principal |
number |
Principal portion of the payment |
interest |
number |
Interest portion of the payment |
remainingBalance |
number |
Balance remaining after payment |
Calculates auto loan payments using the standard amortization formula, with term in months.
import { AutoLoan } from "calculators";
const al = new AutoLoan(35000, 5000, 4.5, 60);
// constructor(vehiclePrice, downPayment, ratePercentage, termMonths)
const result = al.calculate();
console.log(result.monthlyPayment); // 559.28
console.log(result.totalInterest); // 3556.80| Parameter | Type | Description |
|---|---|---|
vehiclePrice |
number |
Vehicle price (must be > 0) |
downPayment |
number |
Down payment (>= 0, must be < price) |
ratePercentage |
number |
Annual rate, 0 < rate < 100 |
termMonths |
number |
Loan term in months (positive integer) |
Returns: AutoLoanResult
| Field | Type | Description |
|---|---|---|
loanAmount |
number |
Financed amount (price - down payment) |
monthlyPayment |
number |
Monthly payment |
totalPaid |
number |
Total of all payments |
totalInterest |
number |
Total interest paid |
Calculates how long it takes to pay off a debt with a fixed monthly payment.
import { DebtPayoff } from "calculators";
const dp = new DebtPayoff(5000, 18, 200);
// constructor(balance, ratePercentage, monthlyPayment)
const result = dp.calculate();
console.log(result.months); // 32
console.log(result.totalInterest); // 1313.97| Parameter | Type | Description |
|---|---|---|
balance |
number |
Outstanding debt (must be > 0) |
ratePercentage |
number |
Annual rate, 0 < rate < 100 |
monthlyPayment |
number |
Fixed payment (must exceed monthly interest) |
Returns: DebtPayoffResult
| Field | Type | Description |
|---|---|---|
months |
number |
Number of months to pay off |
totalPaid |
number |
Total amount paid |
totalInterest |
number |
Total interest paid |
Projects the future value of retirement savings with regular contributions.
import { RetirementSavings } from "calculators";
const rs = new RetirementSavings(50000, 500, 7, 25);
// constructor(initialBalance, monthlyContribution, ratePercentage, years)
const result = rs.calculate();
console.log(result.futureValue); // 676,570+ (varies by rounding)
console.log(result.totalContributions); // 150000
console.log(result.totalInterest); // futureValue - 50000 - 150000| Parameter | Type | Description |
|---|---|---|
initialBalance |
number |
Starting balance (>= 0) |
monthlyContribution |
number |
Monthly contribution (>= 0) |
ratePercentage |
number |
Annual return rate, 0-100 |
years |
number |
Investment horizon (must be > 0) |
Returns: RetirementResult
| Field | Type | Description |
|---|---|---|
futureValue |
number |
Projected total value |
totalContributions |
number |
Sum of all contributions |
totalInterest |
number |
Total growth from interest |
Calculates the present value of a future sum: PV = FV / (1 + r)^n.
import { PresentValue } from "calculators";
const pv = new PresentValue(10000, 5, 10);
// constructor(futureValue, ratePercentage, years)
console.log(pv.calculate()); // 6139.13| Parameter | Type | Description |
|---|---|---|
futureValue |
number |
Future amount (must be > 0) |
ratePercentage |
number |
Discount rate, 0-100 |
years |
number |
Time period (must be > 0) |
Returns: number — the present value.
Calculates the monthly savings needed to reach a financial goal.
import { SavingsGoal } from "calculators";
const sg = new SavingsGoal(50000, 10000, 5, 5);
// constructor(goalAmount, currentSavings, ratePercentage, years)
const result = sg.calculate();
console.log(result.monthlySavings); // ~588
console.log(result.totalContributions); // monthlySavings * 60
console.log(result.interestEarned); // goal - currentSavings - contributions| Parameter | Type | Description |
|---|---|---|
goalAmount |
number |
Target amount (must be > 0) |
currentSavings |
number |
Current savings (>= 0, must be < goal) |
ratePercentage |
number |
Annual return rate, 0-100 |
years |
number |
Time horizon (must be > 0) |
Returns: SavingsGoalResult
| Field | Type | Description |
|---|---|---|
monthlySavings |
number |
Required monthly savings |
totalContributions |
number |
Total amount contributed |
interestEarned |
number |
Total interest earned |
Simulates periodic fixed-amount investments at varying prices.
import { DollarCostAveraging } from "calculators";
const prices = [50, 45, 55, 40, 60];
const dca = new DollarCostAveraging(100, prices);
// constructor(investmentPerPeriod, prices)
const result = dca.calculate();
console.log(result.totalShares);
console.log(result.averageCostPerShare);
console.log(result.totalInvested); // 500| Parameter | Type | Description |
|---|---|---|
investmentPerPeriod |
number |
Fixed investment amount (must be > 0) |
prices |
number[] |
Array of prices per period (all must be > 0) |
Returns: DCAResult
| Field | Type | Description |
|---|---|---|
totalInvested |
number |
Total amount invested |
totalShares |
number |
Total shares purchased |
averageCostPerShare |
number |
Average cost per share |
currentValue |
number |
Value at the final price |
gainLoss |
number |
Dollar gain or loss (currentValue - totalInvested) |
Calculates return on investment with optional annualized ROI.
import { ROI } from "calculators";
const roi = new ROI(10000, 15000, 3);
// constructor(cost, revenue, years?)
const result = roi.calculate();
console.log(result.roi); // 50.00
console.log(result.annualizedRoi); // 14.47
console.log(result.netProfit); // 5000.00| Parameter | Type | Description |
|---|---|---|
cost |
number |
Initial investment (must be > 0) |
revenue |
number |
Total return (>= 0) |
years |
number? |
Optional holding period for annualized ROI |
Returns: ROIResult
| Field | Type | Description |
|---|---|---|
roi |
number |
ROI as a percentage |
annualizedRoi |
number? |
Annualized ROI (if years provided) |
netProfit |
number |
Revenue minus cost |
Calculates the real rate of return after inflation using the Fisher equation.
import { InflationAdjustedReturn } from "calculators";
const iar = new InflationAdjustedReturn(10, 3);
// constructor(nominalRatePercentage, inflationRatePercentage)
const result = iar.calculate();
console.log(result.realReturn); // 6.80| Parameter | Type | Description |
|---|---|---|
nominalRatePercentage |
number |
Nominal return rate, 0-100 |
inflationRatePercentage |
number |
Inflation rate, 0 to <100 |
Returns: InflationAdjustedResult
| Field | Type | Description |
|---|---|---|
realReturn |
number |
Real return percentage |
nominalRate |
number |
Input nominal rate |
inflationRate |
number |
Input inflation rate |
Calculates progressive income tax with bracket breakdown.
import { TaxBracket } from "calculators";
import type { Bracket } from "calculators";
const brackets: Bracket[] = [
{ min: 0, max: 11000, rate: 10 },
{ min: 11000, max: 44725, rate: 12 },
{ min: 44725, max: 95375, rate: 22 },
{ min: 95375, max: 182100, rate: 24 },
];
const tb = new TaxBracket(100000, brackets);
const result = tb.calculate();
console.log(result.totalTax); // Total tax owed
console.log(result.effectiveRate); // Effective tax rate %
console.log(result.marginalRate); // Highest applicable bracket rate
console.log(result.brackets); // Per-bracket breakdown| Parameter | Type | Description |
|---|---|---|
income |
number |
Taxable income (must be > 0) |
taxBrackets |
Bracket[] |
Array of tax brackets (non-overlapping) |
Each Bracket:
| Field | Type | Description |
|---|---|---|
min |
number |
Bracket lower bound (>= 0) |
max |
number |
Bracket upper bound (must be > min) |
rate |
number |
Tax rate for this bracket, 0-100 |
Returns: TaxBracketResult
| Field | Type | Description |
|---|---|---|
totalTax |
number |
Total tax owed |
effectiveRate |
number |
Effective tax rate as a percentage |
marginalRate |
number |
Marginal (highest applicable) tax rate |
brackets |
BracketBreakdown[] |
Per-bracket tax detail |
Calculates the break-even point in units and revenue.
import { BreakEven } from "calculators";
const be = new BreakEven(50000, 100, 60);
// constructor(fixedCosts, pricePerUnit, variableCostPerUnit)
const result = be.calculate();
console.log(result.breakEvenUnits); // 1250
console.log(result.breakEvenRevenue); // 125000
console.log(result.contributionMargin); // 40| Parameter | Type | Description |
|---|---|---|
fixedCosts |
number |
Total fixed costs (must be > 0) |
pricePerUnit |
number |
Selling price per unit (must be > 0) |
variableCostPerUnit |
number |
Variable cost per unit (>= 0, must be < price) |
Returns: BreakEvenResult
| Field | Type | Description |
|---|---|---|
breakEvenUnits |
number |
Units to sell to break even (rounded up) |
breakEvenRevenue |
number |
Revenue at break-even point |
contributionMargin |
number |
Price minus variable cost per unit |
contributionMarginRatio |
number |
Contribution margin as a percentage of price |
| Command | Description |
|---|---|
npm test |
Run all tests with Jest |
npm run build |
Compile TypeScript to dist/ |
npm run publish-lib |
Build and publish to npm |
npm run publish-beta |
Build and publish with beta tag |
npm run publish-dryrun |
Build and simulate publish |
npm run patch |
Bump patch version |
npm run minor |
Bump minor version |
npm run major |
Bump major version |
The library includes 173 tests across 15 test suites covering:
- Input validation (boundary values, negative inputs, zero values)
- Mathematical correctness (verified against known financial formulas)
- Edge cases (rounding precision, exact payoff, single-period calculations)
- Safety guards (loop limits, maximum term lengths)
npm testCalculators/
app/
index.ts # Library entry point (all exports)
calculators/
SimpleInterest.ts
CompoundInterest.ts
mortgage.ts
LoanAmortization.ts
RetirementSavings.ts
PresentValue.ts
DebtPayoff.ts
ROI.ts
RuleOf72.ts
InflationAdjustedReturn.ts
DollarCostAveraging.ts
AutoLoan.ts
SavingsGoal.ts
BreakEven.ts
TaxBracket.ts
__tests__/ # Jest test suites (one per calculator)
dist/ # Compiled output (generated)
tsconfig.json # Build config (strict mode)
tsconfig.test.json # Test config (extends build)
jest.config.js # Jest configuration
- Fork the repository
- Create a feature branch:
git checkout -b feature/my-calculator - Write tests first (TDD) in
app/__tests__/ - Implement the calculator in
app/calculators/ - Export from
app/index.ts - Ensure all tests pass:
npm test - Ensure the build is clean:
npm run build - Submit a pull request
All calculators follow the same pattern:
export interface MyCalculatorResult {
// typed result fields
}
export default class MyCalculator {
constructor(/* parameters */) { /* assign fields */ }
_validate() {
// throw descriptive errors for invalid inputs
}
calculate(): MyCalculatorResult {
this._validate();
// computation with toFixed(2) rounding
return { /* result */ };
}
}