Make loot-core compatible with exactOptionalPropertyTypes (#4214)

* Make `loot-core` compatible with `exactOptionalPropertyTypes`

* Add release notes
This commit is contained in:
Julian Dominguez-Schatz
2025-02-12 18:43:47 -05:00
committed by GitHub
parent f1a4c888b2
commit 454f019f7a
14 changed files with 67 additions and 42 deletions

View File

@@ -194,7 +194,7 @@ function handleSyncResponse(
}
type SyncAccountsPayload = {
id?: AccountEntity['id'];
id?: AccountEntity['id'] | undefined;
};
export const syncAccounts = createAppAsyncThunk(

View File

@@ -168,8 +168,8 @@ export function duplicateBudget({
loadBudget = 'none',
cloudSync,
}: {
id?: string;
cloudId?: string;
id?: string | undefined;
cloudId?: string | undefined;
oldName: string;
newName: string;
managePage?: boolean;
@@ -178,7 +178,7 @@ export function duplicateBudget({
* cloudSync is used to determine if the duplicate budget
* should be synced to the server
*/
cloudSync?: boolean;
cloudSync: boolean;
}) {
return async (dispatch: AppDispatch) => {
try {

View File

@@ -27,9 +27,9 @@ function toJS(rows: CustomReportData[]) {
includeCurrentInterval: row.include_current === 1,
showUncategorized: row.show_uncategorized === 1,
graphType: row.graph_type,
conditions: row.conditions,
...(row.conditions && { conditions: row.conditions }),
conditionsOp: row.conditions_op ?? 'and',
data: row.metadata,
...(row.metadata && { metadata: row.metadata }),
};
return report;
});

View File

@@ -91,7 +91,9 @@ export function useTransactions({
}
},
onError,
options: { pageCount: optionsRef.current.pageCount },
options: optionsRef.current.pageCount
? { pageCount: optionsRef.current.pageCount }
: {},
});
return () => {
@@ -122,7 +124,7 @@ export function useTransactions({
return {
transactions,
isLoading,
error,
...(error && { error }),
reload,
loadMore,
isLoadingMore,
@@ -274,10 +276,11 @@ export function usePreviewTransactions(): UsePreviewTransactionsResult {
};
}, [scheduleTransactions, schedules, statuses, upcomingLength]);
const returnError = error || scheduleQueryError;
return {
data: previewTransactions,
isLoading: isLoading || isSchedulesLoading,
error: error || scheduleQueryError,
...(returnError && { error: returnError }),
};
}

View File

@@ -53,6 +53,6 @@ export function useQuery<Response = unknown>(
return {
data,
isLoading,
error,
...(error && { error }),
};
}

View File

@@ -42,7 +42,7 @@ type FinanceModals = {
'select-linked-accounts': {
accounts: unknown[];
requisitionId?: string;
upgradingAccountId?: string;
upgradingAccountId?: string | undefined;
syncSource?: AccountSyncSource;
};
@@ -74,7 +74,7 @@ type FinanceModals = {
onMoveExternal: (arg: {
institutionId: string;
}) => Promise<{ error: string } | { data: unknown }>;
onClose?: () => void;
onClose?: (() => void) | undefined;
onSuccess: (data: GoCardlessToken) => Promise<void>;
};

View File

@@ -1,21 +1,23 @@
import type * as constants from '../constants';
export type Notification = {
id?: string;
id?: string | undefined;
// 'warning' is unhandled??
type?: 'message' | 'error' | 'warning';
pre?: string;
title?: string;
pre?: string | undefined;
title?: string | undefined;
message: string;
sticky?: boolean;
timeout?: number;
button?: {
title: string;
action: () => void | Promise<void>;
};
messageActions?: Record<string, () => void>;
onClose?: () => void;
internal?: string;
sticky?: boolean | undefined;
timeout?: number | undefined;
button?:
| {
title: string;
action: () => void | Promise<void>;
}
| undefined;
messageActions?: Record<string, () => void> | undefined;
onClose?: (() => void) | undefined;
internal?: string | undefined;
};
type NotificationWithId = Notification & { id: string };

View File

@@ -98,9 +98,13 @@ export function generateCategoryGroups(
return definition.map(group => {
const g = generateCategoryGroup(group.name ?? '', group.is_income);
if (!group.categories) {
return g;
}
return {
...g,
categories: group.categories?.map(cat =>
categories: group.categories.map(cat =>
generateCategory(cat.name, g.id, cat.is_income),
),
};
@@ -117,9 +121,9 @@ function _generateTransaction(
notes: 'Notes',
account: data.account,
date: data.date || monthUtils.currentDay(),
category: data.category,
sort_order: data.sort_order != null ? data.sort_order : 1,
cleared: false,
...(data.category && { category: data.category }),
};
}
@@ -186,7 +190,7 @@ export function generateTransactions(
{
account: accountId,
category: groupId,
amount: isSplit ? 50 : undefined,
...(isSplit && { amount: 50 }),
sort_order: i,
},
isSplit ? 30 : undefined,

View File

@@ -54,7 +54,7 @@ export const categoryModel = {
name: category.name,
is_income: category.is_income ? true : false,
hidden: category.hidden ? true : false,
group_id: category.cat_group,
...(category.cat_group && { group_id: category.cat_group }),
};
},

View File

@@ -1,6 +1,6 @@
// TODO: normalize error types
export class PostError extends Error {
meta?: { meta: string };
meta: { meta: string } | undefined;
reason: string;
type: 'PostError';
@@ -24,14 +24,15 @@ export class HTTPError extends Error {
}
export class SyncError extends Error {
meta?:
meta:
| {
isMissingKey: boolean;
}
| {
error: { message: string; stack: string };
query: { sql: string; params: Array<string | number> };
};
}
| undefined;
reason: string;
constructor(

View File

@@ -19,7 +19,7 @@ export function resetTracer() {
}
export function execTracer<T>() {
const queue: Array<{ name: string; data?: T }> = [];
const queue: Array<{ name: string; data?: T | undefined }> = [];
let hasStarted = false;
let waitingFor: null | {
name: string;

View File

@@ -249,9 +249,12 @@ export function updateTransaction(
let child = t;
if (trans.id === transaction.id) {
const { payee: childPayee, ...rest } = t;
const newPayee =
childPayee === trans.payee ? transaction.payee : childPayee;
child = {
...t,
payee: t.payee === trans.payee ? transaction.payee : t.payee,
...rest,
...(newPayee != null ? { payee: newPayee } : {}),
};
} else if (t.id === transaction.id) {
child = transaction;
@@ -260,7 +263,10 @@ export function updateTransaction(
return makeChild(parent, child);
});
return recalculateSplit({ ...parent, subtransactions: sub });
return recalculateSplit({
...parent,
...(sub && { subtransactions: sub }),
});
} else {
return transaction;
}
@@ -283,7 +289,10 @@ export function deleteTransaction(
} satisfies TransactionEntity;
} else {
const sub = trans.subtransactions?.filter(t => t.id !== id);
return recalculateSplit({ ...trans, subtransactions: sub });
return recalculateSplit({
...trans,
...(sub && { subtransactions: sub }),
});
}
} else {
return null;

View File

@@ -192,7 +192,7 @@ export interface ServerHandlers {
'secret-check': (arg: string) => Promise<string | { error?: string }>;
'gocardless-poll-web-token': (arg: {
upgradingAccountId?: string;
upgradingAccountId?: string | undefined;
requisitionId: string;
}) => Promise<
{ error: 'unknown' } | { error: 'timeout' } | { data: GoCardlessToken }
@@ -228,7 +228,7 @@ export interface ServerHandlers {
'gocardless-poll-web-token-stop': () => Promise<'ok'>;
'gocardless-create-web-token': (arg: {
upgradingAccountId?: string;
upgradingAccountId?: string | undefined;
institutionId: string;
accessValidForDays: number;
}) => Promise<
@@ -385,8 +385,8 @@ export interface ServerHandlers {
'close-budget': () => Promise<'ok'>;
'delete-budget': (arg: {
id?: string;
cloudFileId?: string;
id?: string | undefined;
cloudFileId?: string | undefined;
}) => Promise<'ok' | 'fail'>;
/**
@@ -399,8 +399,8 @@ export interface ServerHandlers {
* @returns {Promise<string>} The ID of the newly created budget.
*/
'duplicate-budget': (arg: {
id?: string;
cloudId?: string;
id?: string | undefined;
cloudId?: string | undefined;
newName: string;
cloudSync?: boolean;
open: 'none' | 'original' | 'copy';

View File

@@ -0,0 +1,6 @@
---
category: Maintenance
authors: [jfdoming]
---
Make `loot-core` compatible with `exactOptionalPropertyTypes`