diff --git a/packages/desktop-client/src/components/modals/ImportTransactionsModal/Transaction.tsx b/packages/desktop-client/src/components/modals/ImportTransactionsModal/Transaction.tsx
index 6808cf18ed2..e6c325ca9c8 100644
--- a/packages/desktop-client/src/components/modals/ImportTransactionsModal/Transaction.tsx
+++ b/packages/desktop-client/src/components/modals/ImportTransactionsModal/Transaction.tsx
@@ -218,12 +218,12 @@ export function Transaction({
: {}),
}}
title={
- inflow === null && outflow === null
+ outflow === null
? 'Invalid: unable to parse the value'
: amountToCurrency(outflow)
}
>
- {amountToCurrency(outflow)}
+ {amountToCurrency(outflow || 0)}
- {amountToCurrency(inflow)}
+ {amountToCurrency(inflow || 0)}
>
) : (
@@ -271,7 +271,7 @@ export function Transaction({
: amountToCurrency(amount)
}
>
- {amountToCurrency(amount)}
+ {amountToCurrency(amount || 0)}
>
)}
diff --git a/packages/desktop-client/src/components/reports/graphs/AreaGraph.tsx b/packages/desktop-client/src/components/reports/graphs/AreaGraph.tsx
index f97b9edaf30..fea3afb4291 100644
--- a/packages/desktop-client/src/components/reports/graphs/AreaGraph.tsx
+++ b/packages/desktop-client/src/components/reports/graphs/AreaGraph.tsx
@@ -33,11 +33,11 @@ import { renderCustomLabel } from './renderCustomLabel';
type PayloadItem = {
payload: {
date: string;
- totalAssets: number | string;
- totalDebts: number | string;
- netAssets: number | string;
- netDebts: number | string;
- totalTotals: number | string;
+ totalAssets: number;
+ totalDebts: number;
+ netAssets: number;
+ netDebts: number;
+ totalTotals: number;
};
};
@@ -141,7 +141,9 @@ const customLabel = ({
((typeof props.value === 'number' ? props.value : 0) > 0 ? 10 : -10);
const textAnchor = props.index === 0 ? 'left' : 'middle';
const display =
- props.value !== 0 ? `${amountToCurrencyNoDecimal(props.value)}` : '';
+ typeof props.value !== 'string' && props.value !== 0
+ ? `${amountToCurrencyNoDecimal(props.value || 0)}`
+ : '';
const textSize = adjustTextSize({ sized: width, type: 'area' });
return renderCustomLabel(calcX, calcY, textAnchor, display, textSize);
diff --git a/packages/desktop-client/src/components/reports/graphs/BarGraph.tsx b/packages/desktop-client/src/components/reports/graphs/BarGraph.tsx
index e32a8414419..bcfc762de98 100644
--- a/packages/desktop-client/src/components/reports/graphs/BarGraph.tsx
+++ b/packages/desktop-client/src/components/reports/graphs/BarGraph.tsx
@@ -50,13 +50,13 @@ type PayloadChild = {
type PayloadItem = {
payload: {
name: string;
- totalAssets: number | string;
- totalDebts: number | string;
- netAssets: number | string;
- netDebts: number | string;
- totalTotals: number | string;
- networth: number | string;
- totalChange: number | string;
+ totalAssets: number;
+ totalDebts: number;
+ netAssets: number;
+ netDebts: number;
+ totalTotals: number;
+ networth: number;
+ totalChange: number;
children: [PayloadChild];
};
};
diff --git a/packages/desktop-client/src/components/reports/reports/SpendingCard.tsx b/packages/desktop-client/src/components/reports/reports/SpendingCard.tsx
index cebea01c081..e7916fc8360 100644
--- a/packages/desktop-client/src/components/reports/reports/SpendingCard.tsx
+++ b/packages/desktop-client/src/components/reports/reports/SpendingCard.tsx
@@ -136,7 +136,7 @@ export function SpendingCard({
{data &&
(difference && difference > 0 ? '+' : '') +
- amountToCurrency(difference)}
+ amountToCurrency(difference || 0)}
diff --git a/packages/loot-core/src/shared/util.ts b/packages/loot-core/src/shared/util.ts
index 92ea4e4b4a5..9c603384b57 100644
--- a/packages/loot-core/src/shared/util.ts
+++ b/packages/loot-core/src/shared/util.ts
@@ -329,6 +329,21 @@ export function getNumberFormat({
// Number utilities
+/**
+ * The exact amount.
+ */
+export type Amount = number;
+/**
+ * The exact amount that is formatted based on the configured number format.
+ * For example, 123.45 would be '123.45' or '123,45'.
+ */
+export type CurrencyAmount = string;
+/**
+ * The amount with the decimal point removed.
+ * For example, 123.45 would be 12345.
+ */
+export type IntegerAmount = number;
+
// We dont use `Number.MAX_SAFE_NUMBER` and such here because those
// numbers are so large that it's not safe to convert them to floats
// (i.e. N / 100). For example, `9007199254740987 / 100 ===
@@ -353,39 +368,41 @@ export function safeNumber(value: number) {
return value;
}
-export function toRelaxedNumber(value: string) {
- return integerToAmount(currencyToInteger(value) || 0);
+export function toRelaxedNumber(currencyAmount: CurrencyAmount): Amount {
+ return integerToAmount(currencyToInteger(currencyAmount) || 0);
}
export function integerToCurrency(
- n: number,
+ integerAmount: IntegerAmount,
formatter = getNumberFormat().formatter,
) {
- return formatter.format(safeNumber(n) / 100);
+ return formatter.format(safeNumber(integerAmount) / 100);
}
-export function amountToCurrency(n) {
- return getNumberFormat().formatter.format(n);
+export function amountToCurrency(amount: Amount): CurrencyAmount {
+ return getNumberFormat().formatter.format(amount);
}
-export function amountToCurrencyNoDecimal(n) {
+export function amountToCurrencyNoDecimal(amount: Amount): CurrencyAmount {
return getNumberFormat({
...numberFormatConfig,
hideFraction: true,
- }).formatter.format(n);
+ }).formatter.format(amount);
}
-export function currencyToAmount(str: string) {
+export function currencyToAmount(
+ currencyAmount: CurrencyAmount,
+): Amount | null {
let amount;
if (getNumberFormat().separatorRegex) {
amount = parseFloat(
- str
+ currencyAmount
.replace(getNumberFormat().regex, '')
.replace(getNumberFormat().separatorRegex, '.'),
);
} else {
amount = parseFloat(
- str
+ currencyAmount
.replace(getNumberFormat().regex, '')
.replace(getNumberFormat().separator, '.'),
);
@@ -393,12 +410,14 @@ export function currencyToAmount(str: string) {
return isNaN(amount) ? null : amount;
}
-export function currencyToInteger(str: string) {
- const amount = currencyToAmount(str);
+export function currencyToInteger(
+ currencyAmount: CurrencyAmount,
+): IntegerAmount | null {
+ const amount = currencyToAmount(currencyAmount);
return amount == null ? null : amountToInteger(amount);
}
-export function stringToInteger(str: string) {
+export function stringToInteger(str: string): number | null {
const amount = parseInt(str.replace(/[^-0-9.,]/g, ''));
if (!isNaN(amount)) {
return amount;
@@ -406,12 +425,12 @@ export function stringToInteger(str: string) {
return null;
}
-export function amountToInteger(n: number) {
- return Math.round(n * 100);
+export function amountToInteger(amount: Amount): IntegerAmount {
+ return Math.round(amount * 100);
}
-export function integerToAmount(n) {
- return parseFloat((safeNumber(n) / 100).toFixed(2));
+export function integerToAmount(integerAmount: IntegerAmount): Amount {
+ return parseFloat((safeNumber(integerAmount) / 100).toFixed(2));
}
// This is used when the input format could be anything (from
diff --git a/upcoming-release-notes/4207.md b/upcoming-release-notes/4207.md
new file mode 100644
index 00000000000..e3bcb7fd8f6
--- /dev/null
+++ b/upcoming-release-notes/4207.md
@@ -0,0 +1,6 @@
+---
+category: Maintenance
+authors: [joel-jeremy]
+---
+
+Add type to the the amount utils to clarify what's the difference between amount, integer amount, and currency.