From 63583452865368be2246df9e16cccd24c55e0180 Mon Sep 17 00:00:00 2001 From: Julian Dominguez-Schatz Date: Sat, 14 Feb 2026 10:58:25 -0500 Subject: [PATCH] Fix some low-hanging-fruit `@ts-strict-ignore` (#6969) * Fix low-hanging-fruit `@ts-strict-ignore` * Add release notes * A few more --- .../src/components/AnimatedRefresh.tsx | 5 ++-- .../src/components/FinancesApp.tsx | 11 ++++++-- .../desktop-client/src/components/Notes.tsx | 5 ++-- .../src/components/Notifications.tsx | 11 ++++++-- .../desktop-client/src/components/alerts.tsx | 3 +- .../src/hooks/useScrollListener.tsx | 2 +- packages/desktop-client/src/index.tsx | 4 ++- packages/desktop-client/src/sync-events.ts | 9 ++++-- .../budget/category-template-context.ts | 28 ++++++++++++------- upcoming-release-notes/6969.md | 6 ++++ 10 files changed, 57 insertions(+), 27 deletions(-) create mode 100644 upcoming-release-notes/6969.md diff --git a/packages/desktop-client/src/components/AnimatedRefresh.tsx b/packages/desktop-client/src/components/AnimatedRefresh.tsx index d5ac370d8c..3aa346534a 100644 --- a/packages/desktop-client/src/components/AnimatedRefresh.tsx +++ b/packages/desktop-client/src/components/AnimatedRefresh.tsx @@ -1,4 +1,3 @@ -// @ts-strict-ignore import React from 'react'; import type { CSSProperties } from 'react'; @@ -26,7 +25,9 @@ export function AnimatedRefresh({ }: AnimatedRefreshProps) { return ( { @@ -81,7 +86,7 @@ function RouterBehaviors() { export function FinancesApp() { const { isNarrowWidth } = useResponsive(); - useMetaThemeColor(isNarrowWidth ? theme.mobileViewTheme : null); + useMetaThemeColor(isNarrowWidth ? theme.mobileViewTheme : undefined); const dispatch = useDispatch(); const { t } = useTranslation(); diff --git a/packages/desktop-client/src/components/Notes.tsx b/packages/desktop-client/src/components/Notes.tsx index 75a4ce4026..58b7bf9498 100644 --- a/packages/desktop-client/src/components/Notes.tsx +++ b/packages/desktop-client/src/components/Notes.tsx @@ -1,4 +1,3 @@ -// @ts-strict-ignore import React, { useEffect, useRef } from 'react'; import { useTranslation } from 'react-i18next'; import ReactMarkdown from 'react-markdown'; @@ -49,7 +48,7 @@ export function Notes({ useEffect(() => { if (focused && editable) { - textAreaRef.current.focus(); + textAreaRef.current?.focus(); } }, [focused, editable]); @@ -71,7 +70,7 @@ export function Notes({ placeholder={t('Notes (markdown supported)')} /> ) : ( - + @@ -131,7 +130,13 @@ function Notification({ const error = type === 'error'; const processedMessage = useMemo( - () => compileMessage(message, messageActions, setOverlayLoading, onRemove), + () => + compileMessage( + message, + messageActions ?? {}, + setOverlayLoading, + onRemove, + ), [message, messageActions, onRemove, setOverlayLoading], ); diff --git a/packages/desktop-client/src/components/alerts.tsx b/packages/desktop-client/src/components/alerts.tsx index 738366b1e5..bdd5673b4b 100644 --- a/packages/desktop-client/src/components/alerts.tsx +++ b/packages/desktop-client/src/components/alerts.tsx @@ -1,4 +1,3 @@ -// @ts-strict-ignore import React from 'react'; import type { ComponentType, CSSProperties, ReactNode } from 'react'; @@ -12,7 +11,7 @@ import { theme } from '@actual-app/components/theme'; import { View } from '@actual-app/components/view'; type AlertProps = { - icon?: ComponentType<{ width?: number; style?: CSSProperties }>; + icon: ComponentType<{ width?: number; style?: CSSProperties }>; color?: string; backgroundColor?: string; style?: CSSProperties; diff --git a/packages/desktop-client/src/hooks/useScrollListener.tsx b/packages/desktop-client/src/hooks/useScrollListener.tsx index bef953609c..519b850ae7 100644 --- a/packages/desktop-client/src/hooks/useScrollListener.tsx +++ b/packages/desktop-client/src/hooks/useScrollListener.tsx @@ -32,7 +32,7 @@ type IScrollContext = { const ScrollContext = createContext(undefined); type ScrollProviderProps = { - scrollableRef: RefObject; + scrollableRef: RefObject; isDisabled?: boolean; delayMs?: number; children?: ReactNode; diff --git a/packages/desktop-client/src/index.tsx b/packages/desktop-client/src/index.tsx index b3ffe6e932..3961f3a37b 100644 --- a/packages/desktop-client/src/index.tsx +++ b/packages/desktop-client/src/index.tsx @@ -1,4 +1,3 @@ -// @ts-strict-ignore // This file will initialize the app if we are in a real browser // environment (not electron) import './browser-preload'; @@ -86,6 +85,9 @@ window.$query = aqlQuery; window.$q = q; const container = document.getElementById('root'); +if (!container) { + throw new Error('Root container not found'); +} const root = createRoot(container); root.render( diff --git a/packages/desktop-client/src/sync-events.ts b/packages/desktop-client/src/sync-events.ts index 20995aeb6a..d2ccb3d549 100644 --- a/packages/desktop-client/src/sync-events.ts +++ b/packages/desktop-client/src/sync-events.ts @@ -1,4 +1,3 @@ -// @ts-strict-ignore import type { QueryClient } from '@tanstack/react-query'; import { t } from 'i18next'; @@ -253,6 +252,12 @@ export function listenForSyncEvent(store: AppStore, queryClient: QueryClient) { // few things depending on the state, and we try to show an // appropriate message and call to action to fix it. const { cloudFileId } = store.getState().prefs.local; + if (!cloudFileId) { + console.error( + 'Received file-has-reset or file-has-new-key error but no cloudFileId in prefs', + ); + break; + } notif = { title: t('Syncing has been reset on this cloud file'), @@ -277,7 +282,7 @@ export function listenForSyncEvent(store: AppStore, queryClient: QueryClient) { break; case 'encrypt-failure': case 'decrypt-failure': - if (event.meta.isMissingKey) { + if (event.meta?.isMissingKey) { notif = { title: t('Missing encryption key'), message: t( diff --git a/packages/loot-core/src/server/budget/category-template-context.ts b/packages/loot-core/src/server/budget/category-template-context.ts index 1f19b2843a..5be1e85aa2 100644 --- a/packages/loot-core/src/server/budget/category-template-context.ts +++ b/packages/loot-core/src/server/budget/category-template-context.ts @@ -1,4 +1,3 @@ -// @ts-strict-ignore import { getCurrency } from 'loot-core/shared/currencies'; import type { Currency } from 'loot-core/shared/currencies'; import { q } from 'loot-core/shared/query'; @@ -241,11 +240,11 @@ export class CategoryTemplateContext { // don't overbudget when using a priority unless income category if (priority > 0 && available < 0 && !this.category.is_income) { - this.fullAmount += toBudget; + this.fullAmount = (this.fullAmount || 0) + toBudget; toBudget = Math.max(0, toBudget + available); this.toBudgetAmount += toBudget; } else { - this.fullAmount += toBudget; + this.fullAmount = (this.fullAmount || 0) + toBudget; this.toBudgetAmount += toBudget; } return this.category.is_income ? -toBudget : toBudget; @@ -301,9 +300,9 @@ export class CategoryTemplateContext { readonly hideDecimal: boolean = false; private remainderWeight: number = 0; private toBudgetAmount: number = 0; // amount that will be budgeted by the templates - private fullAmount: number = null; // the full requested amount, start null for remainder only cats - private isLongGoal: boolean = null; //defaulting the goals to null so templates can be unset - private goalAmount: number = null; + private fullAmount: number | null = null; // the full requested amount, start null for remainder only cats + private isLongGoal: boolean | null = null; //defaulting the goals to null so templates can be unset + private goalAmount: number | null = null; private fromLastMonth = 0; // leftover from last month private limitMet = false; private limitExcess: number = 0; @@ -593,7 +592,7 @@ export class CategoryTemplateContext { break; case 'year': // the addYears function doesn't return the month number, so use addMonths - dateShiftFunction = (date, numPeriods) => + dateShiftFunction = (date: string | Date, numPeriods: number) => monthUtils.addMonths(date, numPeriods * 12); break; default: @@ -716,6 +715,11 @@ export class CategoryTemplateContext { const incomeCat = (await db.getCategories()).find( c => c.is_income && c.name.toLowerCase() === cat, ); + if (!incomeCat) { + throw new Error( + `Income category "${template.category}" not found for percentage template`, + ); + } monthlyIncome = await getSheetValue( sheetName, `sum-amount-${incomeCat.id}`, @@ -772,7 +776,7 @@ export class CategoryTemplateContext { ); const savedInfo = []; let totalNeeded = 0; - let shortNumMonths; + let workingShortNumMonths; //find shortest time period for (let i = 0; i < byTemplates.length; i++) { const template = byTemplates[i]; @@ -794,12 +798,16 @@ export class CategoryTemplateContext { ); } savedInfo.push({ numMonths, period }); - if (numMonths < shortNumMonths || shortNumMonths === undefined) { - shortNumMonths = numMonths; + if ( + workingShortNumMonths === undefined || + numMonths < workingShortNumMonths + ) { + workingShortNumMonths = numMonths; } } // calculate needed funds per template + const shortNumMonths = workingShortNumMonths || 0; for (let i = 0; i < byTemplates.length; i++) { const template = byTemplates[i]; const numMonths = savedInfo[i].numMonths; diff --git a/upcoming-release-notes/6969.md b/upcoming-release-notes/6969.md new file mode 100644 index 0000000000..96b36bc731 --- /dev/null +++ b/upcoming-release-notes/6969.md @@ -0,0 +1,6 @@ +--- +category: Maintenance +authors: [jfdoming] +--- + +Fix some low-hanging-fruit `@ts-strict-ignore`