diff --git a/packages/desktop-client/src/components/autocomplete/CategoryAutocomplete.tsx b/packages/desktop-client/src/components/autocomplete/CategoryAutocomplete.tsx
index b9b418a54a2729673df667eef7cd034b0da1a226..3f1d16cdade799a327cfb468db50bba287b5d73a 100644
--- a/packages/desktop-client/src/components/autocomplete/CategoryAutocomplete.tsx
+++ b/packages/desktop-client/src/components/autocomplete/CategoryAutocomplete.tsx
@@ -36,7 +36,7 @@ type CategoryAutocompleteItem = CategoryEntity & {
   group?: CategoryGroupEntity;
 };
 
-export type CategoryListProps = {
+type CategoryListProps = {
   items: CategoryAutocompleteItem[];
   getItemProps?: (arg: {
     item: CategoryAutocompleteItem;
diff --git a/packages/desktop-client/src/components/reports/CategorySelector.tsx b/packages/desktop-client/src/components/reports/CategorySelector.tsx
index d9639de36214dc6f3c83cd67e8f2dbaf2b107e10..317ca37275327a5b27f4bd6a350a0183667037f6 100644
--- a/packages/desktop-client/src/components/reports/CategorySelector.tsx
+++ b/packages/desktop-client/src/components/reports/CategorySelector.tsx
@@ -12,7 +12,6 @@ import {
   SvgViewHide,
   SvgViewShow,
 } from '../../icons/v2';
-import { type CategoryListProps } from '../autocomplete/CategoryAutocomplete';
 import { Button } from '../common/Button';
 import { Text } from '../common/Text';
 import { View } from '../common/View';
@@ -22,8 +21,8 @@ import { GraphButton } from './GraphButton';
 
 type CategorySelectorProps = {
   categoryGroups: Array<CategoryGroupEntity>;
-  selectedCategories: CategoryListProps['items'];
-  setSelectedCategories: (selectedCategories: CategoryEntity[]) => null;
+  selectedCategories: CategoryEntity[];
+  setSelectedCategories: (selectedCategories: CategoryEntity[]) => void;
   showHiddenCategories?: boolean;
 };
 
diff --git a/packages/desktop-client/src/components/reports/Overview.jsx b/packages/desktop-client/src/components/reports/Overview.tsx
similarity index 94%
rename from packages/desktop-client/src/components/reports/Overview.jsx
rename to packages/desktop-client/src/components/reports/Overview.tsx
index 06ecef0c81535bcf3f446011d8fb08cd50387378..550e039c63f831d714199408876d56325793de46 100644
--- a/packages/desktop-client/src/components/reports/Overview.jsx
+++ b/packages/desktop-client/src/components/reports/Overview.tsx
@@ -32,11 +32,9 @@ export function Overview() {
     <View
       style={{
         ...styles.page,
-        ...{
-          padding: 15,
-          paddingTop: 0,
-          minWidth: isNarrowWidth ? null : 700,
-        },
+        padding: 15,
+        paddingTop: 0,
+        minWidth: isNarrowWidth ? undefined : 700,
       }}
     >
       {customReportsFeatureFlag && !isNarrowWidth && (
diff --git a/packages/desktop-client/src/components/reports/ReportOptions.ts b/packages/desktop-client/src/components/reports/ReportOptions.ts
index acad7f742d7921f41fa60dbc938d3923ce7f9c71..e8c7bd8becf915c40fc00e470fdc52c76ecb38b1 100644
--- a/packages/desktop-client/src/components/reports/ReportOptions.ts
+++ b/packages/desktop-client/src/components/reports/ReportOptions.ts
@@ -44,95 +44,118 @@ const groupByOptions = [
   { description: 'Interval' },
 ];
 
-const dateRangeOptions = [
+export type dateRangeProps = {
+  description: string;
+  name: number | string;
+  type?: string;
+  Daily: boolean;
+  Weekly: boolean;
+  Monthly: boolean;
+  Yearly: boolean;
+};
+
+const dateRangeOptions: dateRangeProps[] = [
   {
     description: 'This week',
-    type: 'Weeks',
     name: 0,
-    Yearly: false,
-    Monthly: false,
+    type: 'Weeks',
     Daily: true,
     Weekly: true,
+    Monthly: false,
+    Yearly: false,
   },
   {
     description: 'Last week',
-    type: 'Weeks',
     name: 1,
-    Yearly: false,
-    Monthly: false,
+    type: 'Weeks',
     Daily: true,
     Weekly: true,
+    Monthly: false,
+    Yearly: false,
   },
   {
     description: 'This month',
-    type: 'Months',
     name: 0,
-    Yearly: false,
-    Monthly: true,
+    type: 'Months',
     Daily: true,
     Weekly: true,
+    Monthly: true,
+    Yearly: false,
   },
   {
     description: 'Last month',
-    type: 'Months',
     name: 1,
-    Yearly: false,
-    Monthly: true,
+    type: 'Months',
     Daily: true,
     Weekly: true,
+    Monthly: true,
+    Yearly: false,
   },
   {
     description: 'Last 3 months',
-    type: 'Months',
     name: 2,
-    Yearly: false,
-    Monthly: true,
+    type: 'Months',
     Daily: true,
     Weekly: true,
+    Monthly: true,
+    Yearly: false,
   },
   {
     description: 'Last 6 months',
-    type: 'Months',
     name: 5,
-    Yearly: false,
-    Monthly: true,
+    type: 'Months',
     Daily: false,
+    Weekly: false,
+    Monthly: true,
+    Yearly: false,
   },
   {
     description: 'Last 12 months',
-    type: 'Months',
     name: 11,
-    Yearly: false,
-    Monthly: true,
+    type: 'Months',
     Daily: false,
+    Weekly: false,
+    Monthly: true,
+    Yearly: false,
   },
   {
     description: 'Year to date',
     name: 'yearToDate',
-    Yearly: true,
-    Monthly: true,
     Daily: true,
     Weekly: true,
+    Monthly: true,
+    Yearly: true,
   },
   {
     description: 'Last year',
     name: 'lastYear',
-    Yearly: true,
-    Monthly: true,
     Daily: true,
     Weekly: true,
+    Monthly: true,
+    Yearly: true,
   },
   {
     description: 'All time',
     name: 'allTime',
-    Yearly: true,
-    Monthly: true,
     Daily: true,
     Weekly: true,
+    Monthly: true,
+    Yearly: true,
   },
 ];
 
-const intervalOptions = [
+type intervalOptionsProps = {
+  description: string;
+  name: 'Day' | 'Week' | 'Month' | 'Year';
+  format: string;
+  range:
+    | 'dayRangeInclusive'
+    | 'weekRangeInclusive'
+    | 'rangeInclusive'
+    | 'yearRangeInclusive';
+};
+
+const intervalOptions: intervalOptionsProps[] = [
   {
     description: 'Daily',
     name: 'Day',
@@ -175,15 +198,19 @@ export const ReportOptions = {
     dateRangeOptions.map(item => [item.description, item.type]),
   ),
   interval: intervalOptions,
-  intervalMap: new Map(
+  intervalMap: new Map<string, 'Day' | 'Week' | 'Month' | 'Year'>(
     intervalOptions.map(item => [item.description, item.name]),
   ),
   intervalFormat: new Map(
     intervalOptions.map(item => [item.description, item.format]),
   ),
-  intervalRange: new Map(
-    intervalOptions.map(item => [item.description, item.range]),
-  ),
+  intervalRange: new Map<
+    string,
+    | 'dayRangeInclusive'
+    | 'weekRangeInclusive'
+    | 'rangeInclusive'
+    | 'yearRangeInclusive'
+  >(intervalOptions.map(item => [item.description, item.range])),
 };
 
 export type QueryDataEntity = {
diff --git a/packages/desktop-client/src/components/reports/ReportRouter.jsx b/packages/desktop-client/src/components/reports/ReportRouter.tsx
similarity index 100%
rename from packages/desktop-client/src/components/reports/ReportRouter.jsx
rename to packages/desktop-client/src/components/reports/ReportRouter.tsx
diff --git a/packages/desktop-client/src/components/reports/ReportSidebar.jsx b/packages/desktop-client/src/components/reports/ReportSidebar.tsx
similarity index 84%
rename from packages/desktop-client/src/components/reports/ReportSidebar.jsx
rename to packages/desktop-client/src/components/reports/ReportSidebar.tsx
index 23f949a4a9b253d757e1cae53bd379f03491e974..33fbe5c128c38d377ec72c6933922eba3518a173 100644
--- a/packages/desktop-client/src/components/reports/ReportSidebar.jsx
+++ b/packages/desktop-client/src/components/reports/ReportSidebar.tsx
@@ -1,8 +1,12 @@
 import React, { useState } from 'react';
 
 import * as monthUtils from 'loot-core/src/shared/months';
+import { type CategoryEntity } from 'loot-core/types/models/category';
+import { type CategoryGroupEntity } from 'loot-core/types/models/category-group';
+import { type CustomReportEntity } from 'loot-core/types/models/reports';
+import { type LocalPrefs } from 'loot-core/types/prefs';
 
-import { theme } from '../../style';
+import { theme } from '../../style/theme';
 import { Button } from '../common/Button';
 import { Menu } from '../common/Menu';
 import { Select } from '../common/Select';
@@ -14,10 +18,42 @@ import { CategorySelector } from './CategorySelector';
 import { defaultsList } from './disabledList';
 import { getLiveRange } from './getLiveRange';
 import { ModeButton } from './ModeButton';
-import { ReportOptions } from './ReportOptions';
+import { type dateRangeProps, ReportOptions } from './ReportOptions';
 import { validateEnd, validateStart } from './reportRanges';
 import { setSessionReport } from './setSessionReport';
 
+type ReportSidebarProps = {
+  customReportItems: CustomReportEntity;
+  categories: { list: CategoryEntity[]; grouped: CategoryGroupEntity[] };
+  dateRangeLine: number;
+  allIntervals: { name: string; pretty: string }[];
+  setDateRange: (value: string) => void;
+  setGraphType: (value: string) => void;
+  setGroupBy: (value: string) => void;
+  setInterval: (value: string) => void;
+  setBalanceType: (value: string) => void;
+  setMode: (value: string) => void;
+  setIsDateStatic: (value: boolean) => void;
+  setShowEmpty: (value: boolean) => void;
+  setShowOffBudget: (value: boolean) => void;
+  setShowHiddenCategories: (value: boolean) => void;
+  setShowUncategorized: (value: boolean) => void;
+  setSelectedCategories: (value: CategoryEntity[]) => void;
+  onChangeDates: (dateStart: string, dateEnd: string) => void;
+  onReportChange: ({
+    savedReport,
+    type,
+  }: {
+    savedReport?: CustomReportEntity;
+    type: string;
+  }) => void;
+  disabledItems: (type: string) => string[];
+  defaultItems: (item: string) => void;
+  defaultModeItems: (graph: string, item: string) => void;
+  earliestTransaction: string;
+  firstDayOfWeekIdx: LocalPrefs['firstDayOfWeekIdx'];
+};
+
 export function ReportSidebar({
   customReportItems,
   categories,
@@ -42,9 +78,9 @@ export function ReportSidebar({
   defaultModeItems,
   earliestTransaction,
   firstDayOfWeekIdx,
-}) {
+}: ReportSidebarProps) {
   const [menuOpen, setMenuOpen] = useState(false);
-  const onSelectRange = cond => {
+  const onSelectRange = (cond: string) => {
     setSessionReport('dateRange', cond);
     onReportChange({ type: 'modify' });
     setDateRange(cond);
@@ -53,11 +89,11 @@ export function ReportSidebar({
     );
   };
 
-  const onChangeMode = cond => {
+  const onChangeMode = (cond: string) => {
     setSessionReport('mode', cond);
     onReportChange({ type: 'modify' });
     setMode(cond);
-    let graph;
+    let graph = '';
     if (cond === 'time') {
       if (customReportItems.graphType === 'BarGraph') {
         setSessionReport('graphType', 'StackedBarGraph');
@@ -74,14 +110,14 @@ export function ReportSidebar({
     defaultModeItems(graph, cond);
   };
 
-  const onChangeSplit = cond => {
+  const onChangeSplit = (cond: string) => {
     setSessionReport('groupBy', cond);
     onReportChange({ type: 'modify' });
     setGroupBy(cond);
     defaultItems(cond);
   };
 
-  const onChangeBalanceType = cond => {
+  const onChangeBalanceType = (cond: string) => {
     setSessionReport('balanceType', cond);
     onReportChange({ type: 'modify' });
     setBalanceType(cond);
@@ -187,11 +223,11 @@ export function ReportSidebar({
               onReportChange({ type: 'modify' });
               if (
                 ReportOptions.dateRange
-                  .filter(int => !int[e])
+                  .filter(d => !d[e as keyof dateRangeProps])
                   .map(int => int.description)
                   .includes(customReportItems.dateRange)
               ) {
-                onSelectRange(defaultsList.intervalRange.get(e));
+                onSelectRange(defaultsList.intervalRange.get(e) || '');
               }
             }}
             options={ReportOptions.interval.map(option => [
@@ -353,9 +389,11 @@ export function ReportSidebar({
                 onSelectRange(e);
               }}
               options={ReportOptions.dateRange
-                .filter(f => f[customReportItems.interval])
+                .filter(
+                  f => f[customReportItems.interval as keyof dateRangeProps],
+                )
                 .map(option => [option.description, option.description])}
-              line={dateRangeLine > 0 && dateRangeLine}
+              line={dateRangeLine > 0 ? dateRangeLine : undefined}
             />
           </View>
         ) : (
@@ -385,7 +423,9 @@ export function ReportSidebar({
                 value={customReportItems.startDate}
                 defaultLabel={monthUtils.format(
                   customReportItems.startDate,
-                  ReportOptions.intervalFormat.get(customReportItems.interval),
+                  ReportOptions.intervalFormat.get(
+                    customReportItems.interval,
+                  ) || '',
                 )}
                 options={allIntervals.map(({ name, pretty }) => [name, pretty])}
               />
@@ -415,7 +455,9 @@ export function ReportSidebar({
                 value={customReportItems.endDate}
                 defaultLabel={monthUtils.format(
                   customReportItems.endDate,
-                  ReportOptions.intervalFormat.get(customReportItems.interval),
+                  ReportOptions.intervalFormat.get(
+                    customReportItems.interval,
+                  ) || '',
                 )}
                 options={allIntervals.map(({ name, pretty }) => [name, pretty])}
               />
@@ -443,7 +485,7 @@ export function ReportSidebar({
               ? true
               : false;
           })}
-          selectedCategories={customReportItems.selectedCategories}
+          selectedCategories={customReportItems.selectedCategories || []}
           setSelectedCategories={e => {
             setSelectedCategories(e);
             onReportChange({ type: 'modify' });
diff --git a/packages/desktop-client/src/components/reports/ReportTopbar.jsx b/packages/desktop-client/src/components/reports/ReportTopbar.tsx
similarity index 77%
rename from packages/desktop-client/src/components/reports/ReportTopbar.jsx
rename to packages/desktop-client/src/components/reports/ReportTopbar.tsx
index 0bb9c45f99e1633b2a1111c23ca9cbf030d094f7..042b781a1188e243b13fc6422df1336c95af4f96 100644
--- a/packages/desktop-client/src/components/reports/ReportTopbar.jsx
+++ b/packages/desktop-client/src/components/reports/ReportTopbar.tsx
@@ -1,5 +1,8 @@
 import React from 'react';
 
+import { type CustomReportEntity } from 'loot-core/types/models/reports';
+import { type RuleConditionEntity } from 'loot-core/types/models/rule';
+
 import {
   SvgCalculator,
   SvgChart,
@@ -18,6 +21,27 @@ import { GraphButton } from './GraphButton';
 import { SaveReport } from './SaveReport';
 import { setSessionReport } from './setSessionReport';
 
+type ReportTopbarProps = {
+  customReportItems: CustomReportEntity;
+  report: CustomReportEntity;
+  savedStatus: string;
+  setGraphType: (value: string) => void;
+  viewLegend: boolean;
+  viewSummary: boolean;
+  viewLabels: boolean;
+  onApplyFilter: (newFilter: RuleConditionEntity) => void;
+  onChangeViews: (viewType: string) => void;
+  onReportChange: ({
+    savedReport,
+    type,
+  }: {
+    savedReport?: CustomReportEntity;
+    type: string;
+  }) => void;
+  isItemDisabled: (type: string) => boolean;
+  defaultItems: (item: string) => void;
+};
+
 export function ReportTopbar({
   customReportItems,
   report,
@@ -29,10 +53,10 @@ export function ReportTopbar({
   onApplyFilter,
   onChangeViews,
   onReportChange,
-  disabledItems,
+  isItemDisabled,
   defaultItems,
-}) {
-  const onChangeGraph = cond => {
+}: ReportTopbarProps) {
+  const onChangeGraph = (cond: string) => {
     setSessionReport('graphType', cond);
     onReportChange({ type: 'modify' });
     setGraphType(cond);
@@ -55,7 +79,7 @@ export function ReportTopbar({
           onChangeGraph('TableGraph');
         }}
         style={{ marginRight: 15 }}
-        disabled={disabledItems('TableGraph')}
+        disabled={isItemDisabled('TableGraph')}
       >
         <SvgQueue width={15} height={15} />
       </GraphButton>
@@ -73,7 +97,7 @@ export function ReportTopbar({
           );
         }}
         style={{ marginRight: 15 }}
-        disabled={disabledItems(
+        disabled={isItemDisabled(
           customReportItems.mode === 'total' ? 'BarGraph' : 'StackedBarGraph',
         )}
       >
@@ -86,7 +110,7 @@ export function ReportTopbar({
           onChangeGraph('LineGraph');
         }}
         style={{ marginRight: 15 }}
-        disabled={disabledItems('LineGraph')}
+        disabled={isItemDisabled('LineGraph')}
       >
         <SvgChart width={15} height={15} />
       </GraphButton>
@@ -97,7 +121,7 @@ export function ReportTopbar({
           onChangeGraph('AreaGraph');
         }}
         style={{ marginRight: 15 }}
-        disabled={disabledItems('AreaGraph')}
+        disabled={isItemDisabled('AreaGraph')}
       >
         <SvgChartArea width={15} height={15} />
       </GraphButton>
@@ -108,7 +132,7 @@ export function ReportTopbar({
           onChangeGraph('DonutGraph');
         }}
         style={{ marginRight: 15 }}
-        disabled={disabledItems('DonutGraph')}
+        disabled={isItemDisabled('DonutGraph')}
       >
         <SvgChartPie width={15} height={15} />
       </GraphButton>
@@ -128,7 +152,7 @@ export function ReportTopbar({
         }}
         style={{ marginRight: 15 }}
         title="Show Legend"
-        disabled={disabledItems('ShowLegend')}
+        disabled={isItemDisabled('ShowLegend')}
       >
         <SvgListBullet width={15} height={15} />
       </GraphButton>
@@ -149,7 +173,7 @@ export function ReportTopbar({
         }}
         style={{ marginRight: 15 }}
         title="Show Labels"
-        disabled={disabledItems('ShowLabels')}
+        disabled={isItemDisabled('ShowLabels')}
       >
         <SvgTag width={15} height={15} />
       </GraphButton>
@@ -165,11 +189,15 @@ export function ReportTopbar({
       <FilterButton
         compact
         hover
-        onApply={e => {
-          setSessionReport('conditions', [...customReportItems.conditions, e]);
+        onApply={(e: RuleConditionEntity) => {
+          setSessionReport('conditions', [
+            ...(customReportItems.conditions ?? []),
+            e,
+          ]);
           onApplyFilter(e);
           onReportChange({ type: 'modify' });
         }}
+        exclude={[]}
       />
       <View style={{ flex: 1 }} />
       <SaveReport
diff --git a/packages/desktop-client/src/components/reports/disabledList.ts b/packages/desktop-client/src/components/reports/disabledList.ts
index b641a59f28884554a70b3029ea9ac5e5826cae49..ad3caadb6e95f94d0c2590961e969b704c662ef7 100644
--- a/packages/desktop-client/src/components/reports/disabledList.ts
+++ b/packages/desktop-client/src/components/reports/disabledList.ts
@@ -17,7 +17,16 @@ const intervalOptions = [
   },
 ];
 
-const totalGraphOptions = [
+type graphOptions = {
+  description: string;
+  disabledSplit: string[];
+  defaultSplit: string;
+  disabledType: string[];
+  defaultType: string;
+  disableLegend?: boolean;
+  disableLabel?: boolean;
+};
+const totalGraphOptions: graphOptions[] = [
   {
     description: 'TableGraph',
     disabledSplit: [],
@@ -51,7 +60,7 @@ const totalGraphOptions = [
   },
 ];
 
-const timeGraphOptions = [
+const timeGraphOptions: graphOptions[] = [
   {
     description: 'TableGraph',
     disabledSplit: ['Interval'],
@@ -94,35 +103,67 @@ const modeOptions = [
   },
 ];
 
+export function disabledGraphList(
+  item: string,
+  newGraph: string,
+  type: 'disabledSplit' | 'disabledType',
+) {
+  const graphList = modeOptions.find(d => d.description === item);
+  if (!graphList) {
+    return [];
+  }
+
+  const disabledList = graphList.graphs.find(e => e.description === newGraph);
+  if (!disabledList) {
+    return [];
+  }
+
+  return disabledList[type];
+}
+
+export function disabledLegendLabel(
+  item: string,
+  newGraph: string,
+  type: 'disableLegend' | 'disableLabel',
+) {
+  const graphList = modeOptions.find(d => d.description === item);
+  if (!graphList) {
+    return false;
+  }
+
+  const disableLegendLabel = graphList.graphs.find(
+    e => e.description === newGraph,
+  );
+  if (!disableLegendLabel) {
+    return false;
+  }
+
+  return disableLegendLabel[type];
+}
+
+export function defaultsGraphList(
+  item: string,
+  newGraph: string,
+  type: 'defaultSplit' | 'defaultType',
+) {
+  const graphList = modeOptions.find(d => d.description === item);
+  if (!graphList) {
+    return '';
+  }
+
+  const defaultItem = graphList.graphs.find(e => e.description === newGraph);
+  if (!defaultItem) {
+    return '';
+  }
+
+  return defaultItem[type];
+}
+
 export const disabledList = {
   mode: modeOptions,
   modeGraphsMap: new Map(
     modeOptions.map(item => [item.description, item.disabledGraph]),
   ),
-  graphSplitMap: new Map(
-    modeOptions.map(item => [
-      item.description,
-      new Map([...item.graphs].map(f => [f.description, f.disabledSplit])),
-    ]),
-  ),
-  graphTypeMap: new Map(
-    modeOptions.map(item => [
-      item.description,
-      new Map([...item.graphs].map(f => [f.description, f.disabledType])),
-    ]),
-  ),
-  graphLegendMap: new Map(
-    modeOptions.map(item => [
-      item.description,
-      new Map([...item.graphs].map(f => [f.description, f.disableLegend])),
-    ]),
-  ),
-  graphLabelsMap: new Map(
-    modeOptions.map(item => [
-      item.description,
-      new Map([...item.graphs].map(f => [f.description, f.disableLabel])),
-    ]),
-  ),
 };
 
 export const defaultsList = {
@@ -130,18 +171,6 @@ export const defaultsList = {
   modeGraphsMap: new Map(
     modeOptions.map(item => [item.description, item.defaultGraph]),
   ),
-  graphSplitMap: new Map(
-    modeOptions.map(item => [
-      item.description,
-      new Map([...item.graphs].map(f => [f.description, f.defaultSplit])),
-    ]),
-  ),
-  graphTypeMap: new Map(
-    modeOptions.map(item => [
-      item.description,
-      new Map([...item.graphs].map(f => [f.description, f.defaultType])),
-    ]),
-  ),
   intervalRange: new Map(
     intervalOptions.map(item => [item.description, item.defaultRange]),
   ),
diff --git a/packages/desktop-client/src/components/reports/getLiveRange.ts b/packages/desktop-client/src/components/reports/getLiveRange.ts
index a7030ebe680edbc7ca32708e6e02b0d71ec28143..437892f6fe5423c35770a58240bab50321f35073 100644
--- a/packages/desktop-client/src/components/reports/getLiveRange.ts
+++ b/packages/desktop-client/src/components/reports/getLiveRange.ts
@@ -8,9 +8,9 @@ export function getLiveRange(
   cond: string,
   earliestTransaction: string,
   firstDayOfWeekIdx?: LocalPrefs['firstDayOfWeekIdx'],
-) {
-  let dateStart;
-  let dateEnd;
+): [string, string] {
+  let dateStart = earliestTransaction;
+  let dateEnd = monthUtils.currentDay();
   const rangeName = ReportOptions.dateRangeMap.get(cond);
   switch (rangeName) {
     case 'yearToDate':
diff --git a/packages/desktop-client/src/components/reports/reportRanges.ts b/packages/desktop-client/src/components/reports/reportRanges.ts
index 0acf4d42b2866ad60903cd5ddd240f71552cf4b3..720954f597e780455d8b908871b1fc5ebdab1e11 100644
--- a/packages/desktop-client/src/components/reports/reportRanges.ts
+++ b/packages/desktop-client/src/components/reports/reportRanges.ts
@@ -7,7 +7,7 @@ export function validateStart(
   end: string,
   interval?: string,
   firstDayOfWeekIdx?: LocalPrefs['firstDayOfWeekIdx'],
-) {
+): [string, string] {
   let addDays;
   let dateStart;
   switch (interval) {
@@ -47,7 +47,7 @@ export function validateEnd(
   end: string,
   interval?: string,
   firstDayOfWeekIdx?: LocalPrefs['firstDayOfWeekIdx'],
-) {
+): [string, string] {
   let subDays;
   let dateEnd;
   switch (interval) {
@@ -98,7 +98,7 @@ function boundedRange(
   end: string,
   interval?: string,
   firstDayOfWeekIdx?: LocalPrefs['firstDayOfWeekIdx'],
-) {
+): [string, string] {
   let latest;
   switch (interval) {
     case 'Daily':
diff --git a/packages/desktop-client/src/components/reports/reports/CustomReport.jsx b/packages/desktop-client/src/components/reports/reports/CustomReport.tsx
similarity index 70%
rename from packages/desktop-client/src/components/reports/reports/CustomReport.jsx
rename to packages/desktop-client/src/components/reports/reports/CustomReport.tsx
index cc375de1dbcf5b66577d9128b32a832af77978c5..53320dd83fb5121f16a97aee84b271314528712c 100644
--- a/packages/desktop-client/src/components/reports/reports/CustomReport.jsx
+++ b/packages/desktop-client/src/components/reports/reports/CustomReport.tsx
@@ -6,27 +6,44 @@ import * as d from 'date-fns';
 import { send } from 'loot-core/src/platform/client/fetch';
 import * as monthUtils from 'loot-core/src/shared/months';
 import { amountToCurrency } from 'loot-core/src/shared/util';
+import { type CategoryEntity } from 'loot-core/types/models/category';
+import {
+  type GroupedEntity,
+  type CustomReportEntity,
+} from 'loot-core/types/models/reports';
+import { type RuleConditionEntity } from 'loot-core/types/models/rule';
 
 import { useAccounts } from '../../../hooks/useAccounts';
 import { useCategories } from '../../../hooks/useCategories';
 import { useFilters } from '../../../hooks/useFilters';
 import { useLocalPref } from '../../../hooks/useLocalPref';
 import { usePayees } from '../../../hooks/usePayees';
+import { SvgArrowLeft } from '../../../icons/v1/ArrowLeft';
 import { useResponsive } from '../../../ResponsiveProvider';
 import { theme, styles } from '../../../style';
 import { AlignedText } from '../../common/AlignedText';
 import { Block } from '../../common/Block';
+import { Link } from '../../common/Link';
 import { Text } from '../../common/Text';
 import { View } from '../../common/View';
 import { AppliedFilters } from '../../filters/AppliedFilters';
 import { PrivacyFilter } from '../../PrivacyFilter';
 import { ChooseGraph } from '../ChooseGraph';
-import { defaultsList, disabledList } from '../disabledList';
+import {
+  defaultsGraphList,
+  defaultsList,
+  disabledGraphList,
+  disabledLegendLabel,
+  disabledList,
+} from '../disabledList';
 import { getLiveRange } from '../getLiveRange';
-import { Header } from '../Header';
 import { LoadingIndicator } from '../LoadingIndicator';
 import { ReportLegend } from '../ReportLegend';
-import { ReportOptions, defaultReport } from '../ReportOptions';
+import {
+  ReportOptions,
+  defaultReport,
+  type dateRangeProps,
+} from '../ReportOptions';
 import { ReportSidebar } from '../ReportSidebar';
 import { ReportSummary } from '../ReportSummary';
 import { ReportTopbar } from '../ReportTopbar';
@@ -60,20 +77,28 @@ export function CustomReport() {
 
   const location = useLocation();
 
-  const prevUrl = sessionStorage.getItem('url');
+  const prevUrl = sessionStorage.getItem('url') || '';
 
   sessionStorage.setItem('prevUrl', prevUrl);
   sessionStorage.setItem('url', location.pathname);
 
   if (['/reports'].includes(prevUrl)) sessionStorage.clear();
 
-  const session = JSON.parse(sessionStorage.getItem('report'));
+  const reportFromSessionStorage = sessionStorage.getItem('report');
+  const session = reportFromSessionStorage
+    ? JSON.parse(reportFromSessionStorage)
+    : {};
   const combine = location.state
     ? location.state.report ?? defaultReport
     : defaultReport;
   const loadReport = { ...combine, ...session };
 
-  const [allIntervals, setAllIntervals] = useState(null);
+  const [allIntervals, setAllIntervals] = useState<
+    Array<{
+      name: string;
+      pretty: string;
+    }>
+  >([]);
 
   const [selectedCategories, setSelectedCategories] = useState(
     loadReport.selectedCategories,
@@ -98,7 +123,8 @@ export function CustomReport() {
   const [dateRange, setDateRange] = useState(loadReport.dateRange);
   const [dataCheck, setDataCheck] = useState(false);
   const dateRangeLine =
-    ReportOptions.dateRange.filter(f => f[interval]).length - 3;
+    ReportOptions.dateRange.filter(f => f[interval as keyof dateRangeProps])
+      .length - 3;
 
   const [intervals, setIntervals] = useState(
     monthUtils.rangeInclusive(startDate, endDate),
@@ -122,34 +148,62 @@ export function CustomReport() {
   useEffect(() => {
     async function run() {
       onApplyFilter(null);
-      report.conditions.forEach(condition => onApplyFilter(condition));
+      report.conditions.forEach((condition: RuleConditionEntity) =>
+        onApplyFilter(condition),
+      );
       const trans = await send('get-earliest-transaction');
       setEarliestTransaction(trans ? trans.date : monthUtils.currentDay());
-      const format =
-        ReportOptions.intervalMap.get(interval).toLowerCase() + 'FromDate';
-      const currentInterval =
-        monthUtils['current' + ReportOptions.intervalMap.get(interval)]();
-      const earliestInterval = trans
-        ? monthUtils[format](d.parseISO(fromDateRepr(trans.date)))
-        : currentInterval;
+      const fromDate =
+        interval === 'Weekly'
+          ? 'dayFromDate'
+          : (((ReportOptions.intervalMap.get(interval) || 'Day').toLowerCase() +
+              'FromDate') as 'dayFromDate' | 'monthFromDate' | 'yearFromDate');
 
-      const rangeProps =
+      const currentDate =
         interval === 'Weekly'
-          ? [earliestInterval, currentInterval, firstDayOfWeekIdx]
-          : [earliestInterval, currentInterval];
-      const allInter = monthUtils[ReportOptions.intervalRange.get(interval)](
-        ...rangeProps,
-      )
-        .map(inter => ({
+          ? 'currentDay'
+          : (('current' +
+              (ReportOptions.intervalMap.get(interval) || 'Day')) as
+              | 'currentDay'
+              | 'currentMonth'
+              | 'currentYear');
+
+      const currentInterval =
+        interval === 'Weekly'
+          ? monthUtils.currentWeek(firstDayOfWeekIdx)
+          : monthUtils[currentDate]();
+      const earliestInterval =
+        interval === 'Weekly'
+          ? monthUtils.weekFromDate(
+              d.parseISO(fromDateRepr(trans.date || monthUtils.currentDay())),
+              firstDayOfWeekIdx,
+            )
+          : monthUtils[fromDate](
+              d.parseISO(fromDateRepr(trans.date || monthUtils.currentDay())),
+            );
+
+      const allIntervals =
+        interval === 'Weekly'
+          ? monthUtils.weekRangeInclusive(
+              earliestInterval,
+              currentInterval,
+              firstDayOfWeekIdx,
+            )
+          : monthUtils[
+              ReportOptions.intervalRange.get(interval) || 'rangeInclusive'
+            ](earliestInterval, currentInterval);
+
+      const allIntervalsMap = allIntervals
+        .map((inter: string) => ({
           name: inter,
           pretty: monthUtils.format(
             inter,
-            ReportOptions.intervalFormat.get(interval),
+            ReportOptions.intervalFormat.get(interval) || '',
           ),
         }))
         .reverse();
 
-      setAllIntervals(allInter);
+      setAllIntervals(allIntervalsMap);
 
       if (!isDateStatic) {
         const [dateStart, dateEnd] = getLiveRange(
@@ -162,19 +216,32 @@ export function CustomReport() {
       }
     }
     run();
-  }, [interval]);
+  }, [
+    interval,
+    dateRange,
+    firstDayOfWeekIdx,
+    isDateStatic,
+    onApplyFilter,
+    report.conditions,
+  ]);
 
   useEffect(() => {
-    const rangeProps =
-      interval === 'Weekly'
-        ? [startDate, endDate, firstDayOfWeekIdx]
-        : [startDate, endDate];
-    setIntervals(
-      monthUtils[ReportOptions.intervalRange.get(interval)](...rangeProps),
-    );
-  }, [interval, startDate, endDate]);
+    const [start, end] = [startDate, endDate];
+    if (interval === 'Weekly') {
+      setIntervals(
+        monthUtils.weekRangeInclusive(start, end, firstDayOfWeekIdx),
+      );
+    } else {
+      setIntervals(
+        monthUtils[
+          ReportOptions.intervalRange.get(interval) || 'rangeInclusive'
+        ](start, end),
+      );
+    }
+  }, [interval, startDate, endDate, firstDayOfWeekIdx]);
 
-  const balanceTypeOp = ReportOptions.balanceTypeMap.get(balanceType);
+  const balanceTypeOp =
+    ReportOptions.balanceTypeMap.get(balanceType) || 'totalDebts';
   const payees = usePayees();
   const accounts = useAccounts();
 
@@ -198,19 +265,15 @@ export function CustomReport() {
     startDate,
     endDate,
     interval,
-    groupBy,
-    balanceType,
+    balanceTypeOp,
     categories,
     selectedCategories,
-    payees,
-    accounts,
     filters,
     conditionsOp,
     showEmpty,
     showOffBudget,
     showHiddenCategories,
     showUncategorized,
-    graphType,
     firstDayOfWeekIdx,
   ]);
 
@@ -241,7 +304,7 @@ export function CustomReport() {
     endDate,
     interval,
     groupBy,
-    balanceType,
+    balanceTypeOp,
     categories,
     selectedCategories,
     payees,
@@ -258,8 +321,11 @@ export function CustomReport() {
   const graphData = useReport('default', getGraphData);
   const groupedData = useReport('grouped', getGroupData);
 
-  const data = { ...graphData, groupedData };
-  const customReportItems = {
+  const data: GroupedEntity = { ...graphData, groupedData } as GroupedEntity;
+
+  const customReportItems: CustomReportEntity = {
+    id: '',
+    name: '',
     startDate,
     endDate,
     isDateStatic,
@@ -276,84 +342,104 @@ export function CustomReport() {
     graphType,
     conditions: filters,
     conditionsOp,
-    data: {},
   };
 
-  const [scrollWidth, setScrollWidth] = useState(0);
+  const [, setScrollWidth] = useState(0);
 
   if (!allIntervals || !data) {
     return null;
   }
 
-  const defaultModeItems = (graph, item) => {
+  const defaultModeItems = (graph: string, item: string) => {
     const chooseGraph = graph || graphType;
-    const newGraph = disabledList.modeGraphsMap.get(item).includes(chooseGraph)
+    const newGraph = (disabledList.modeGraphsMap.get(item) || []).includes(
+      chooseGraph,
+    )
       ? defaultsList.modeGraphsMap.get(item)
       : chooseGraph;
-    if (disabledList.modeGraphsMap.get(item).includes(graphType)) {
+    if ((disabledList.modeGraphsMap.get(item) || []).includes(graphType)) {
       setSessionReport('graphType', newGraph);
       setGraphType(newGraph);
     }
 
-    if (disabledList.graphSplitMap.get(item).get(newGraph).includes(groupBy)) {
-      const cond = defaultsList.graphSplitMap.get(item).get(newGraph);
+    if (
+      (disabledGraphList(item, newGraph, 'disabledSplit') || []).includes(
+        groupBy,
+      )
+    ) {
+      const cond = defaultsGraphList(item, newGraph, 'defaultSplit');
       setSessionReport('groupBy', cond);
       setGroupBy(cond);
     }
 
     if (
-      disabledList.graphTypeMap.get(item).get(newGraph).includes(balanceType)
+      (disabledGraphList(item, newGraph, 'disabledType') || []).includes(
+        balanceType,
+      )
     ) {
-      const cond = defaultsList.graphTypeMap.get(item).get(newGraph);
+      const cond = defaultsGraphList(item, newGraph, 'defaultType');
       setSessionReport('balanceType', cond);
       setBalanceType(cond);
     }
   };
 
-  const defaultItems = item => {
+  const defaultItems = (item: string) => {
     const chooseGraph = ReportOptions.groupBy.includes(item) ? graphType : item;
     if (
-      disabledList.graphSplitMap.get(mode).get(chooseGraph).includes(groupBy)
+      (disabledGraphList(mode, chooseGraph, 'disabledSplit') || []).includes(
+        groupBy,
+      )
     ) {
-      const cond = defaultsList.graphSplitMap.get(mode).get(chooseGraph);
+      const cond = defaultsGraphList(mode, chooseGraph, 'defaultSplit');
       setSessionReport('groupBy', cond);
       setGroupBy(cond);
     }
     if (
-      disabledList.graphTypeMap.get(mode).get(chooseGraph).includes(balanceType)
+      (disabledGraphList(mode, chooseGraph, 'disabledType') || []).includes(
+        balanceType,
+      )
     ) {
-      const cond = defaultsList.graphTypeMap.get(mode).get(chooseGraph);
+      const cond = defaultsGraphList(mode, chooseGraph, 'defaultType');
       setSessionReport('balanceType', cond);
       setBalanceType(cond);
     }
   };
 
-  const disabledItems = type => {
+  const isItemDisabled = (type: string) => {
     switch (type) {
-      case 'split':
-        return disabledList.graphSplitMap.get(mode).get(graphType);
-      case 'type':
-        return graphType === 'BarGraph' && groupBy === 'Interval'
-          ? []
-          : disabledList.graphTypeMap.get(mode).get(graphType);
       case 'ShowLegend': {
-        if (disabledList.graphLegendMap.get(mode).get(graphType)) {
+        if (disabledLegendLabel(mode, graphType, 'disableLegend')) {
           setViewLegendPref(false);
         }
-        return disabledList.graphLegendMap.get(mode).get(graphType);
+        return disabledLegendLabel(mode, graphType, 'disableLegend') || false;
       }
       case 'ShowLabels': {
-        if (disabledList.graphLabelsMap.get(mode).get(graphType)) {
+        if (disabledLegendLabel(mode, graphType, 'disableLabel')) {
           setViewLabelsPref(false);
         }
-        return disabledList.graphLabelsMap.get(mode).get(graphType);
+        return disabledLegendLabel(mode, graphType, 'disableLabel') || false;
       }
       default:
-        return disabledList.modeGraphsMap.get(mode).includes(type);
+        return (
+          (disabledList.modeGraphsMap.get(mode) || []).includes(type) || false
+        );
     }
   };
 
-  const onChangeDates = (dateStart, dateEnd) => {
+  const disabledItems = (type: string) => {
+    switch (type) {
+      case 'split':
+        return disabledGraphList(mode, graphType, 'disabledSplit') || [];
+      case 'type':
+        return graphType === 'BarGraph' && groupBy === 'Interval'
+          ? []
+          : disabledGraphList(mode, graphType, 'disabledType') || [];
+      default:
+        return [];
+    }
+  };
+
+  const onChangeDates = (dateStart: string, dateEnd: string) => {
     setSessionReport('startDate', dateStart);
     setSessionReport('endDate', dateEnd);
     setStartDate(dateStart);
@@ -361,9 +447,9 @@ export function CustomReport() {
     onReportChange({ type: 'modify' });
   };
 
-  const onChangeViews = (viewType, status) => {
+  const onChangeViews = (viewType: string) => {
     if (viewType === 'viewLegend') {
-      setViewLegendPref(status ?? !viewLegend);
+      setViewLegendPref(!viewLegend);
     }
     if (viewType === 'viewSummary') {
       setViewSummaryPref(!viewSummary);
@@ -373,10 +459,12 @@ export function CustomReport() {
     }
   };
 
-  const setReportData = input => {
-    const selectAll = [];
+  const setReportData = (input: CustomReportEntity) => {
+    const selectAll: CategoryEntity[] = [];
     categories.grouped.map(categoryGroup =>
-      categoryGroup.categories.map(category => selectAll.push(category)),
+      (categoryGroup.categories || []).map(category =>
+        selectAll.push(category),
+      ),
     );
 
     setStartDate(input.startDate);
@@ -391,19 +479,20 @@ export function CustomReport() {
     setShowOffBudget(input.showOffBudget);
     setShowHiddenCategories(input.showHiddenCategories);
     setShowUncategorized(input.showUncategorized);
-    setSelectedCategories(input.selectedCategories ?? selectAll);
+    setSelectedCategories(input.selectedCategories || selectAll);
     setGraphType(input.graphType);
     onApplyFilter(null);
-    input.conditions.forEach(condition => onApplyFilter(condition));
+    (input.conditions || []).forEach(condition => onApplyFilter(condition));
     onCondOpChange(input.conditionsOp);
   };
 
-  const onChangeAppliedFilter = (filter, changedElement) => {
-    onReportChange({ type: 'modify' });
-    return changedElement(filter);
-  };
-
-  const onReportChange = ({ savedReport, type }) => {
+  const onReportChange = ({
+    savedReport,
+    type,
+  }: {
+    savedReport?: CustomReportEntity;
+    type: string;
+  }) => {
     switch (type) {
       case 'add-update':
         setSessionReport('savedStatus', 'saved');
@@ -411,7 +500,7 @@ export function CustomReport() {
         setReport(savedReport);
         break;
       case 'rename':
-        setReport({ ...report, name: savedReport.name });
+        setReport({ ...report, name: savedReport?.name || '' });
         break;
       case 'modify':
         if (report.name) {
@@ -434,7 +523,7 @@ export function CustomReport() {
         setSessionReport('savedStatus', 'saved');
         setSavedStatus('saved');
         setReport(savedReport);
-        setReportData(savedReport);
+        setReportData(savedReport || report);
         break;
       default:
     }
@@ -454,7 +543,24 @@ export function CustomReport() {
           flexShrink: 0,
         }}
       >
-        <Header title="Custom Report:" />
+        <View
+          style={{
+            padding: 10,
+            paddingTop: 0,
+            flexShrink: 0,
+          }}
+        >
+          <Link
+            variant="button"
+            type="bare"
+            to="/reports"
+            style={{ marginBottom: '15', alignSelf: 'flex-start' }}
+          >
+            <SvgArrowLeft width={10} height={10} style={{ marginRight: 5 }} />{' '}
+            Back
+          </Link>
+          <View style={styles.veryLargeText}>Custom Report:</View>
+        </View>
         <Text
           style={{
             ...styles.veryLargeText,
@@ -521,17 +627,20 @@ export function CustomReport() {
               onApplyFilter={onApplyFilter}
               onChangeViews={onChangeViews}
               onReportChange={onReportChange}
-              disabledItems={disabledItems}
+              isItemDisabled={isItemDisabled}
               defaultItems={defaultItems}
             />
           )}
           {filters && filters.length > 0 && (
             <View
-              style={{ marginBottom: 10, marginLeft: 5, flexShrink: 0 }}
-              spacing={2}
-              direction="row"
-              justify="flex-start"
-              align="flex-start"
+              style={{
+                marginBottom: 10,
+                marginLeft: 5,
+                flexShrink: 0,
+                flexDirection: 'row',
+                alignItems: 'flex-start',
+                justifyContent: 'flex-start',
+              }}
             >
               <AppliedFilters
                 filters={filters}
@@ -548,13 +657,14 @@ export function CustomReport() {
                     'conditions',
                     filters.filter(f => f !== deletedFilter),
                   );
-                  onChangeAppliedFilter(deletedFilter, onDeleteFilter);
+                  onDeleteFilter(deletedFilter);
+                  onReportChange({ type: 'modify' });
                 }}
                 conditionsOp={conditionsOp}
-                onCondOpChange={filter =>
-                  onChangeAppliedFilter(filter, onCondOpChange)
-                }
-                onUpdateChange={onReportChange}
+                onCondOpChange={co => {
+                  onCondOpChange(co);
+                  onReportChange({ type: 'modify' });
+                }}
               />
             </View>
           )}
@@ -615,8 +725,6 @@ export function CustomReport() {
                     balanceType={balanceType}
                     groupBy={groupBy}
                     interval={interval}
-                    showEmpty={showEmpty}
-                    scrollWidth={scrollWidth}
                     setScrollWidth={setScrollWidth}
                     viewLabels={viewLabels}
                     compact={false}
diff --git a/packages/desktop-client/src/components/reports/spreadsheets/custom-spreadsheet.ts b/packages/desktop-client/src/components/reports/spreadsheets/custom-spreadsheet.ts
index e40e32b659172279b1ed8b67393dc11a38ef33b6..5251bafc1abedcd1de638b78eb69f9d6d51aee1f 100644
--- a/packages/desktop-client/src/components/reports/spreadsheets/custom-spreadsheet.ts
+++ b/packages/desktop-client/src/components/reports/spreadsheets/custom-spreadsheet.ts
@@ -143,13 +143,13 @@ export function createCustomSpreadsheet({
       });
     }
 
-    const rangeProps =
+    const intervals =
       interval === 'Weekly'
-        ? [startDate, endDate, firstDayOfWeekIdx]
-        : [startDate, endDate];
-    const intervals = monthUtils[ReportOptions.intervalRange.get(interval)](
-      ...rangeProps,
-    );
+        ? monthUtils.weekRangeInclusive(startDate, endDate, firstDayOfWeekIdx)
+        : monthUtils[ReportOptions.intervalRange.get(interval)](
+            startDate,
+            endDate,
+          );
 
     let totalAssets = 0;
     let totalDebts = 0;
diff --git a/packages/desktop-client/src/components/reports/spreadsheets/grouped-spreadsheet.ts b/packages/desktop-client/src/components/reports/spreadsheets/grouped-spreadsheet.ts
index 591cb81cfb48006a94fe234123ae134a5906fbfb..b273ccf07f66b397f23d1dc19d694eb025ecd7dd 100644
--- a/packages/desktop-client/src/components/reports/spreadsheets/grouped-spreadsheet.ts
+++ b/packages/desktop-client/src/components/reports/spreadsheets/grouped-spreadsheet.ts
@@ -92,13 +92,13 @@ export function createGroupedSpreadsheet({
       });
     }
 
-    const rangeProps =
+    const intervals =
       interval === 'Weekly'
-        ? [startDate, endDate, firstDayOfWeekIdx]
-        : [startDate, endDate];
-    const intervals = monthUtils[ReportOptions.intervalRange.get(interval)](
-      ...rangeProps,
-    );
+        ? monthUtils.weekRangeInclusive(startDate, endDate, firstDayOfWeekIdx)
+        : monthUtils[ReportOptions.intervalRange.get(interval)](
+            startDate,
+            endDate,
+          );
 
     const groupedData: DataEntity[] = categoryGroup.map(
       group => {
diff --git a/packages/desktop-client/src/hooks/useFilters.ts b/packages/desktop-client/src/hooks/useFilters.ts
index 4bb0e98481f78ec8f3a54e1959fe07c686a870a5..cd8fcaed8688a75b0d90c1b36f8f2f767f808124 100644
--- a/packages/desktop-client/src/hooks/useFilters.ts
+++ b/packages/desktop-client/src/hooks/useFilters.ts
@@ -1,7 +1,11 @@
 // @ts-strict-ignore
 import { useCallback, useMemo, useState } from 'react';
 
-export function useFilters<T>(initialFilters: T[] = []) {
+import { type RuleConditionEntity } from 'loot-core/types/models/rule';
+
+export function useFilters<T extends RuleConditionEntity>(
+  initialFilters: T[] = [],
+) {
   const [filters, setFilters] = useState<T[]>(initialFilters);
   const [conditionsOp, setConditionsOp] = useState<'and' | 'or'>('and');
   const [saved, setSaved] = useState<T[]>(null);
diff --git a/packages/loot-core/src/types/models/reports.d.ts b/packages/loot-core/src/types/models/reports.d.ts
index 3379aeac32caa12a6351e18b598cd3f5c1a245ed..eb9fe981adb9d85a0cb66b4734d3e288c7e53e42 100644
--- a/packages/loot-core/src/types/models/reports.d.ts
+++ b/packages/loot-core/src/types/models/reports.d.ts
@@ -60,7 +60,7 @@ export interface SpendingEntity {
 export interface GroupedEntity {
   data?: DataEntity[];
   intervalData: DataEntity[];
-  groupedData?: DataEntity[];
+  groupedData?: DataEntity[] | null;
   legend?: LegendEntity[];
   startDate?: string;
   endDate?: string;
diff --git a/upcoming-release-notes/2707.md b/upcoming-release-notes/2707.md
new file mode 100644
index 0000000000000000000000000000000000000000..57939dac3ea4c22472d1377e8ced4ac48cbd9905
--- /dev/null
+++ b/upcoming-release-notes/2707.md
@@ -0,0 +1,6 @@
+---
+category: Maintenance
+authors: [carkom]
+---
+
+Custom reports: convert final jsx files to typescript.