diff --git a/src/libs/PersonalDetailsUtils.js b/src/libs/PersonalDetailsUtils.js
index 29c49427bc81..ddb24d62ef26 100644
--- a/src/libs/PersonalDetailsUtils.js
+++ b/src/libs/PersonalDetailsUtils.js
@@ -17,8 +17,8 @@ Onyx.connect({
 });
 
 /**
- * @param {Object} passedPersonalDetails
- * @param {Array} pathToDisplayName
+ * @param {Object | Null} passedPersonalDetails
+ * @param {Array | String} pathToDisplayName
  * @param {String} [defaultValue] optional default display name value
  * @returns {String}
  */
diff --git a/src/libs/ReportActionsUtils.ts b/src/libs/ReportActionsUtils.ts
index 98a029bde5de..5d9b4fbdc9cf 100644
--- a/src/libs/ReportActionsUtils.ts
+++ b/src/libs/ReportActionsUtils.ts
@@ -267,7 +267,7 @@ function isConsecutiveActionMadeByPreviousActor(reportActions: ReportAction[] |
 /**
  * Checks if a reportAction is deprecated.
  */
-function isReportActionDeprecated(reportAction: OnyxEntry<ReportAction>, key: string): boolean {
+function isReportActionDeprecated(reportAction: OnyxEntry<ReportAction>, key: string | number): boolean {
     if (!reportAction) {
         return true;
     }
@@ -289,7 +289,7 @@ const supportedActionTypes: ActionName[] = [...Object.values(otherActionTypes),
  * Checks if a reportAction is fit for display, meaning that it's not deprecated, is of a valid
  * and supported type, it's not deleted and also not closed.
  */
-function shouldReportActionBeVisible(reportAction: OnyxEntry<ReportAction>, key: string): boolean {
+function shouldReportActionBeVisible(reportAction: OnyxEntry<ReportAction>, key: string | number): boolean {
     if (!reportAction) {
         return false;
     }
diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js
index 79c1c500b837..de9a4fc8b233 100644
--- a/src/libs/ReportUtils.js
+++ b/src/libs/ReportUtils.js
@@ -108,9 +108,9 @@ function getPolicyType(report, policies) {
 /**
  * Get the policy name from a given report
  * @param {Object} report
- * @param {String} report.policyID
- * @param {String} report.oldPolicyName
- * @param {String} report.policyName
+ * @param {String} [report.policyID]
+ * @param {String} [report.oldPolicyName]
+ * @param {String} [report.policyName]
  * @param {Boolean} [returnEmptyIfNotFound]
  * @param {Object} [policy]
  * @returns {String}
@@ -369,7 +369,7 @@ function isUserCreatedPolicyRoom(report) {
 /**
  * Whether the provided report is a Policy Expense chat.
  * @param {Object} report
- * @param {String} report.chatType
+ * @param {String} [report.chatType]
  * @returns {Boolean}
  */
 function isPolicyExpenseChat(report) {
@@ -395,7 +395,7 @@ function isControlPolicyExpenseReport(report) {
 /**
  * Whether the provided report is a chat room
  * @param {Object} report
- * @param {String} report.chatType
+ * @param {String} [report.chatType]
  * @returns {Boolean}
  */
 function isChatRoom(report) {
@@ -584,8 +584,8 @@ function findLastAccessedReport(reports, ignoreDomainRooms, policies, isFirstTim
 /**
  * Whether the provided report is an archived room
  * @param {Object} report
- * @param {Number} report.stateNum
- * @param {Number} report.statusNum
+ * @param {Number} [report.stateNum]
+ * @param {Number} [report.statusNum]
  * @returns {Boolean}
  */
 function isArchivedRoom(report) {
@@ -3241,7 +3241,7 @@ function shouldHideReport(report, currentReportId) {
  * filter out the majority of reports before filtering out very specific minority of reports.
  *
  * @param {Object} report
- * @param {String} currentReportId
+ * @param {String | Null | Undefined} currentReportId
  * @param {Boolean} isInGSDMode
  * @param {String[]} betas
  * @param {Object} policies
diff --git a/src/libs/SidebarUtils.js b/src/libs/SidebarUtils.ts
similarity index 59%
rename from src/libs/SidebarUtils.js
rename to src/libs/SidebarUtils.ts
index 6b9e6d10fd16..bfe7d2281049 100644
--- a/src/libs/SidebarUtils.js
+++ b/src/libs/SidebarUtils.ts
@@ -1,8 +1,7 @@
 /* eslint-disable rulesdir/prefer-underscore-method */
 import Onyx from 'react-native-onyx';
-import _ from 'underscore';
-import lodashGet from 'lodash/get';
 import Str from 'expensify-common/lib/str';
+import {ValueOf} from 'type-fest';
 import ONYXKEYS from '../ONYXKEYS';
 import * as ReportUtils from './ReportUtils';
 import * as ReportActionsUtils from './ReportActionsUtils';
@@ -13,9 +12,16 @@ import * as CollectionUtils from './CollectionUtils';
 import * as LocalePhoneNumber from './LocalePhoneNumber';
 import * as UserUtils from './UserUtils';
 import * as PersonalDetailsUtils from './PersonalDetailsUtils';
+import ReportAction, {ReportActions} from '../types/onyx/ReportAction';
+import Beta from '../types/onyx/Beta';
+import Policy from '../types/onyx/Policy';
+import Report from '../types/onyx/Report';
+import {PersonalDetails} from '../types/onyx';
+import * as OnyxCommon from '../types/onyx/OnyxCommon';
+
+const visibleReportActionItems: ReportActions = {};
+const lastReportActions: ReportActions = {};
 
-const visibleReportActionItems = {};
-const lastReportActions = {};
 Onyx.connect({
     key: ONYXKEYS.COLLECTION.REPORT_ACTIONS,
     callback: (actions, key) => {
@@ -24,38 +30,37 @@ Onyx.connect({
         }
         const reportID = CollectionUtils.extractCollectionItemID(key);
 
-        const actionsArray = ReportActionsUtils.getSortedReportActions(_.toArray(actions));
-        lastReportActions[reportID] = _.last(actionsArray);
+        const actionsArray: ReportAction[] = ReportActionsUtils.getSortedReportActions(Object.values(actions));
+        lastReportActions[reportID] = actionsArray[actionsArray.length - 1];
 
         // The report is only visible if it is the last action not deleted that
         // does not match a closed or created state.
-        const reportActionsForDisplay = _.filter(
-            actionsArray,
+        const reportActionsForDisplay = actionsArray.filter(
             (reportAction, actionKey) =>
                 ReportActionsUtils.shouldReportActionBeVisible(reportAction, actionKey) &&
                 reportAction.actionName !== CONST.REPORT.ACTIONS.TYPE.CREATED &&
                 reportAction.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE,
         );
-        visibleReportActionItems[reportID] = _.last(reportActionsForDisplay);
+        visibleReportActionItems[reportID] = reportActionsForDisplay[reportActionsForDisplay.length - 1];
     },
 });
 
 // Session can remain stale because the only way for the current user to change is to
 // sign out and sign in, which would clear out all the Onyx
 // data anyway and cause SidebarLinks to rerender.
-let currentUserAccountID;
+let currentUserAccountID: number | undefined;
 Onyx.connect({
     key: ONYXKEYS.SESSION,
-    callback: (val) => {
-        if (!val) {
+    callback: (session) => {
+        if (!session) {
             return;
         }
 
-        currentUserAccountID = val.accountID;
+        currentUserAccountID = session.accountID;
     },
 });
 
-let resolveSidebarIsReadyPromise;
+let resolveSidebarIsReadyPromise: (args?: unknown[]) => void;
 
 let sidebarIsReadyPromise = new Promise((resolve) => {
     resolveSidebarIsReadyPromise = resolve;
@@ -67,15 +72,15 @@ function resetIsSidebarLoadedReadyPromise() {
     });
 }
 
-function isSidebarLoadedReady() {
+function isSidebarLoadedReady(): Promise<unknown> {
     return sidebarIsReadyPromise;
 }
 
-function compareStringDates(stringA, stringB) {
-    if (stringA < stringB) {
+function compareStringDates(a: string, b: string): 0 | 1 | -1 {
+    if (a < b) {
         return -1;
     }
-    if (stringA > stringB) {
+    if (a > b) {
         return 1;
     }
     return 0;
@@ -86,10 +91,10 @@ function setIsSidebarLoadedReady() {
 }
 
 // Define a cache object to store the memoized results
-const reportIDsCache = new Map();
+const reportIDsCache = new Map<string, string[]>();
 
 // Function to set a key-value pair while maintaining the maximum key limit
-function setWithLimit(map, key, value) {
+function setWithLimit<TKey, TValue>(map: Map<TKey, TValue>, key: TKey, value: TValue) {
     if (map.size >= 5) {
         // If the map has reached its limit, remove the first (oldest) key-value pair
         const firstKey = map.keys().next().value;
@@ -102,20 +107,20 @@ function setWithLimit(map, key, value) {
 let hasInitialReportActions = false;
 
 /**
- * @param {String} currentReportId
- * @param {Object} allReportsDict
- * @param {Object} betas
- * @param {String[]} policies
- * @param {String} priorityMode
- * @param {Object} allReportActions
- * @returns {String[]} An array of reportIDs sorted in the proper order
+ * @returns An array of reportIDs sorted in the proper order
  */
-function getOrderedReportIDs(currentReportId, allReportsDict, betas, policies, priorityMode, allReportActions) {
+function getOrderedReportIDs(
+    currentReportId: string | null,
+    allReports: Record<string, Report>,
+    betas: Beta[],
+    policies: Record<string, Policy>,
+    priorityMode: ValueOf<typeof CONST.PRIORITY_MODE>,
+    allReportActions: Record<string, ReportAction[]>,
+): string[] {
     // Generate a unique cache key based on the function arguments
     const cachedReportsKey = JSON.stringify(
-        // eslint-disable-next-line es/no-optional-chaining
-        [currentReportId, allReportsDict, betas, policies, priorityMode, allReportActions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${currentReportId}`]?.length || 1],
-        (key, value) => {
+        [currentReportId, allReports, betas, policies, priorityMode, allReportActions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${currentReportId}`]?.length || 1],
+        (key, value: unknown) => {
             /**
              *  Exclude 'participantAccountIDs', 'participants' and 'lastMessageText' not to overwhelm a cached key value with huge data,
              *  which we don't need to store in a cacheKey
@@ -123,13 +128,15 @@ function getOrderedReportIDs(currentReportId, allReportsDict, betas, policies, p
             if (key === 'participantAccountIDs' || key === 'participants' || key === 'lastMessageText') {
                 return undefined;
             }
+
             return value;
         },
     );
 
     // Check if the result is already in the cache
-    if (reportIDsCache.has(cachedReportsKey) && hasInitialReportActions) {
-        return reportIDsCache.get(cachedReportsKey);
+    const cachedIDs = reportIDsCache.get(cachedReportsKey);
+    if (cachedIDs && hasInitialReportActions) {
+        return cachedIDs;
     }
 
     // This is needed to prevent caching when Onyx is empty for a second render
@@ -137,7 +144,7 @@ function getOrderedReportIDs(currentReportId, allReportsDict, betas, policies, p
 
     const isInGSDMode = priorityMode === CONST.PRIORITY_MODE.GSD;
     const isInDefaultMode = !isInGSDMode;
-    const allReportsDictValues = Object.values(allReportsDict);
+    const allReportsDictValues = Object.values(allReports);
     // Filter out all the reports that shouldn't be displayed
     const reportsToDisplay = allReportsDictValues.filter((report) => ReportUtils.shouldReportBeInOptionList(report, currentReportId, isInGSDMode, betas, policies, allReportActions, true));
 
@@ -158,7 +165,7 @@ function getOrderedReportIDs(currentReportId, allReportsDict, betas, policies, p
         report.displayName = ReportUtils.getReportName(report);
 
         // eslint-disable-next-line no-param-reassign
-        report.iouReportAmount = ReportUtils.getMoneyRequestReimbursableTotal(report, allReportsDict);
+        report.iouReportAmount = ReportUtils.getMoneyRequestReimbursableTotal(report, allReports);
     });
 
     // The LHN is split into five distinct groups, and each group is sorted a little differently. The groups will ALWAYS be in this order:
@@ -171,11 +178,11 @@ function getOrderedReportIDs(currentReportId, allReportsDict, betas, policies, p
     // 5. Archived reports
     //      - Sorted by lastVisibleActionCreated in default (most recent) view mode
     //      - Sorted by reportDisplayName in GSD (focus) view mode
-    const pinnedReports = [];
-    const outstandingIOUReports = [];
-    const draftReports = [];
-    const nonArchivedReports = [];
-    const archivedReports = [];
+    const pinnedReports: Report[] = [];
+    const outstandingIOUReports: Report[] = [];
+    const draftReports: Report[] = [];
+    const nonArchivedReports: Report[] = [];
+    const archivedReports: Report[] = [];
     reportsToDisplay.forEach((report) => {
         if (report.isPinned) {
             pinnedReports.push(report);
@@ -191,47 +198,121 @@ function getOrderedReportIDs(currentReportId, allReportsDict, betas, policies, p
     });
 
     // Sort each group of reports accordingly
-    pinnedReports.sort((a, b) => a.displayName.toLowerCase().localeCompare(b.displayName.toLowerCase()));
-    outstandingIOUReports.sort((a, b) => b.iouReportAmount - a.iouReportAmount || a.displayName.toLowerCase().localeCompare(b.displayName.toLowerCase()));
-    draftReports.sort((a, b) => a.displayName.toLowerCase().localeCompare(b.displayName.toLowerCase()));
+    pinnedReports.sort((a, b) => (a?.displayName && b?.displayName ? a.displayName.toLowerCase().localeCompare(b.displayName.toLowerCase()) : 0));
+    outstandingIOUReports.sort((a, b) => {
+        const compareAmounts = a?.iouReportAmount && b?.iouReportAmount ? b.iouReportAmount - a.iouReportAmount : 0;
+        const compareDisplayNames = a?.displayName && b?.displayName ? a.displayName.toLowerCase().localeCompare(b.displayName.toLowerCase()) : 0;
+        return compareAmounts || compareDisplayNames;
+    });
+    draftReports.sort((a, b) => (a?.displayName && b?.displayName ? a.displayName.toLowerCase().localeCompare(b.displayName.toLowerCase()) : 0));
 
     if (isInDefaultMode) {
-        nonArchivedReports.sort(
-            (a, b) => compareStringDates(b.lastVisibleActionCreated, a.lastVisibleActionCreated) || a.displayName.toLowerCase().localeCompare(b.displayName.toLowerCase()),
-        );
+        nonArchivedReports.sort((a, b) => {
+            const compareDates = a?.lastVisibleActionCreated && b?.lastVisibleActionCreated ? compareStringDates(b.lastVisibleActionCreated, a.lastVisibleActionCreated) : 0;
+            const compareDisplayNames = a?.displayName && b?.displayName ? a.displayName.toLowerCase().localeCompare(b.displayName.toLowerCase()) : 0;
+            return compareDates || compareDisplayNames;
+        });
         // For archived reports ensure that most recent reports are at the top by reversing the order
-        archivedReports.sort((a, b) => compareStringDates(b.lastVisibleActionCreated, a.lastVisibleActionCreated));
+        archivedReports.sort((a, b) => (a?.lastVisibleActionCreated && b?.lastVisibleActionCreated ? compareStringDates(b.lastVisibleActionCreated, a.lastVisibleActionCreated) : 0));
     } else {
-        nonArchivedReports.sort((a, b) => a.displayName.toLowerCase().localeCompare(b.displayName.toLowerCase()));
-        archivedReports.sort((a, b) => a.displayName.toLowerCase().localeCompare(b.displayName.toLowerCase()));
+        nonArchivedReports.sort((a, b) => (a?.displayName && b?.displayName ? a.displayName.toLowerCase().localeCompare(b.displayName.toLowerCase()) : 0));
+        archivedReports.sort((a, b) => (a?.displayName && b?.displayName ? a.displayName.toLowerCase().localeCompare(b.displayName.toLowerCase()) : 0));
     }
 
     // Now that we have all the reports grouped and sorted, they must be flattened into an array and only return the reportID.
     // The order the arrays are concatenated in matters and will determine the order that the groups are displayed in the sidebar.
-    const LHNReports = [].concat(pinnedReports, outstandingIOUReports, draftReports, nonArchivedReports, archivedReports).map((report) => report.reportID);
+    const LHNReports = [...pinnedReports, ...outstandingIOUReports, ...draftReports, ...nonArchivedReports, ...archivedReports].map((report) => report.reportID);
     setWithLimit(reportIDsCache, cachedReportsKey, LHNReports);
     return LHNReports;
 }
 
+type OptionData = {
+    text?: string | null;
+    alternateText?: string | null;
+    pendingAction?: OnyxCommon.PendingAction | null;
+    allReportErrors?: OnyxCommon.Errors | null;
+    brickRoadIndicator?: typeof CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR | '' | null;
+    icons?: Icon[] | null;
+    tooltipText?: string | null;
+    ownerAccountID?: number | null;
+    subtitle?: string | null;
+    participantsList?: PersonalDetails[] | null;
+    login?: string | null;
+    accountID?: number | null;
+    managerID?: number | null;
+    reportID?: string | null;
+    policyID?: string | null;
+    status?: string | null;
+    type?: string | null;
+    stateNum?: ValueOf<typeof CONST.REPORT.STATE_NUM> | null;
+    statusNum?: ValueOf<typeof CONST.REPORT.STATUS> | null;
+    phoneNumber?: string | null;
+    isUnread?: boolean | null;
+    isUnreadWithMention?: boolean | null;
+    hasDraftComment?: boolean | null;
+    keyForList?: string | null;
+    searchText?: string | null;
+    isPinned?: boolean | null;
+    hasOutstandingIOU?: boolean | null;
+    iouReportID?: string | null;
+    isIOUReportOwner?: boolean | null;
+    iouReportAmount?: number | null;
+    isChatRoom?: boolean | null;
+    isArchivedRoom?: boolean | null;
+    shouldShowSubscript?: boolean | null;
+    isPolicyExpenseChat?: boolean | null;
+    isMoneyRequestReport?: boolean | null;
+    isExpenseRequest?: boolean | null;
+    isWaitingOnBankAccount?: boolean | null;
+    isAllowedToComment?: boolean | null;
+    isThread?: boolean | null;
+    isTaskReport?: boolean | null;
+    isWaitingForTaskCompleteFromAssignee?: boolean | null;
+    parentReportID?: string | null;
+    notificationPreference?: string | number | null;
+    displayNamesWithTooltips?: DisplayNamesWithTooltip[] | null;
+    chatType?: ValueOf<typeof CONST.REPORT.CHAT_TYPE> | null;
+};
+
+type DisplayNamesWithTooltip = {
+    displayName?: string;
+    avatar?: string;
+    login?: string;
+    accountID?: number;
+    pronouns?: string;
+};
+
+type ActorDetails = {
+    displayName?: string;
+    accountID?: number;
+};
+
+type Icon = {
+    source?: string;
+    id?: number;
+    type?: string;
+    name?: string;
+};
+
 /**
  * Gets all the data necessary for rendering an OptionRowLHN component
- *
- * @param {Object} report
- * @param {Object} reportActions
- * @param {Object} personalDetails
- * @param {String} preferredLocale
- * @param {Object} [policy]
- * @param {Object} parentReportAction
- * @returns {Object}
  */
-function getOptionData(report, reportActions, personalDetails, preferredLocale, policy, parentReportAction) {
+function getOptionData(
+    report: Report,
+    reportActions: Record<string, ReportAction[]>,
+    personalDetails: Record<number, PersonalDetails>,
+    preferredLocale: ValueOf<typeof CONST.LOCALES>,
+    policy: Policy,
+    parentReportAction: ReportAction,
+): OptionData | undefined {
     // When a user signs out, Onyx is cleared. Due to the lazy rendering with a virtual list, it's possible for
     // this method to be called after the Onyx data has been cleared out. In that case, it's fine to do
     // a null check here and return early.
     if (!report || !personalDetails) {
         return;
     }
-    const result = {
+
+    const result: OptionData = {
         text: null,
         alternateText: null,
         pendingAction: null,
@@ -270,9 +351,8 @@ function getOptionData(report, reportActions, personalDetails, preferredLocale,
         isAllowedToComment: true,
         chatType: null,
     };
-
-    const participantPersonalDetailList = _.values(OptionsListUtils.getPersonalDetailsForAccountIDs(report.participantAccountIDs, personalDetails));
-    const personalDetail = participantPersonalDetailList[0] || {};
+    const participantPersonalDetailList: PersonalDetails[] = Object.values(OptionsListUtils.getPersonalDetailsForAccountIDs(report.participantAccountIDs ?? [], personalDetails));
+    const personalDetail = participantPersonalDetailList[0] ?? {};
 
     result.isThread = ReportUtils.isChatThread(report);
     result.isChatRoom = ReportUtils.isChatRoom(report);
@@ -286,8 +366,8 @@ function getOptionData(report, reportActions, personalDetails, preferredLocale,
     result.isMoneyRequestReport = ReportUtils.isMoneyRequestReport(report);
     result.shouldShowSubscript = ReportUtils.shouldReportShowSubscript(report);
     result.pendingAction = report.pendingFields ? report.pendingFields.addWorkspaceRoom || report.pendingFields.createChat : null;
-    result.allReportErrors = OptionsListUtils.getAllReportErrors(report, reportActions);
-    result.brickRoadIndicator = !_.isEmpty(result.allReportErrors) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : '';
+    result.allReportErrors = OptionsListUtils.getAllReportErrors(report, reportActions) as OnyxCommon.Errors;
+    result.brickRoadIndicator = Object.keys(result.allReportErrors ?? {}).length !== 0 ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : '';
     result.ownerAccountID = report.ownerAccountID;
     result.managerID = report.managerID;
     result.reportID = report.reportID;
@@ -300,31 +380,31 @@ function getOptionData(report, reportActions, personalDetails, preferredLocale,
     result.isPinned = report.isPinned;
     result.iouReportID = report.iouReportID;
     result.keyForList = String(report.reportID);
-    result.tooltipText = ReportUtils.getReportParticipantsTitle(report.participantAccountIDs || []);
+    result.tooltipText = ReportUtils.getReportParticipantsTitle(report.participantAccountIDs ?? []);
     result.hasOutstandingIOU = report.hasOutstandingIOU;
-    result.parentReportID = report.parentReportID || null;
+    result.parentReportID = report.parentReportID ?? null;
     result.isWaitingOnBankAccount = report.isWaitingOnBankAccount;
-    result.notificationPreference = report.notificationPreference || null;
+    result.notificationPreference = report.notificationPreference ?? null;
     result.isAllowedToComment = !ReportUtils.shouldDisableWriteActions(report);
     result.chatType = report.chatType;
 
     const hasMultipleParticipants = participantPersonalDetailList.length > 1 || result.isChatRoom || result.isPolicyExpenseChat;
     const subtitle = ReportUtils.getChatRoomSubtitle(report);
 
-    const login = Str.removeSMSDomain(lodashGet(personalDetail, 'login', ''));
-    const status = lodashGet(personalDetail, 'status', '');
+    const login = Str.removeSMSDomain(personalDetail?.login ?? '');
+    const status = personalDetail?.status ?? '';
     const formattedLogin = Str.isSMSLogin(login) ? LocalePhoneNumber.formatPhoneNumber(login) : login;
 
     // We only create tooltips for the first 10 users or so since some reports have hundreds of users, causing performance to degrade.
-    const displayNamesWithTooltips = ReportUtils.getDisplayNamesWithTooltips((participantPersonalDetailList || []).slice(0, 10), hasMultipleParticipants);
+    const displayNamesWithTooltips: DisplayNamesWithTooltip[] = ReportUtils.getDisplayNamesWithTooltips((participantPersonalDetailList || []).slice(0, 10), hasMultipleParticipants);
     const lastMessageTextFromReport = OptionsListUtils.getLastMessageTextForReport(report);
 
     // If the last actor's details are not currently saved in Onyx Collection,
     // then try to get that from the last report action if that action is valid
     // to get data from.
-    let lastActorDetails = personalDetails[report.lastActorAccountID] || null;
+    let lastActorDetails: ActorDetails | null = report.lastActorAccountID && personalDetails?.[report.lastActorAccountID] ? personalDetails[report.lastActorAccountID] : null;
     if (!lastActorDetails && visibleReportActionItems[report.reportID]) {
-        const lastActorDisplayName = lodashGet(visibleReportActionItems[report.reportID], 'person[0].text');
+        const lastActorDisplayName = visibleReportActionItems[report.reportID]?.person?.[0]?.text;
         lastActorDetails = lastActorDisplayName
             ? {
                   displayName: lastActorDisplayName,
@@ -332,42 +412,35 @@ function getOptionData(report, reportActions, personalDetails, preferredLocale,
               }
             : null;
     }
-    const lastActorDisplayName =
-        hasMultipleParticipants && lastActorDetails && lastActorDetails.accountID && Number(lastActorDetails.accountID) !== currentUserAccountID ? lastActorDetails.displayName : '';
+    const lastActorDisplayName = hasMultipleParticipants && lastActorDetails?.accountID && Number(lastActorDetails.accountID) !== currentUserAccountID ? lastActorDetails.displayName : '';
     let lastMessageText = lastMessageTextFromReport;
 
+    const reportAction = lastReportActions?.[report.reportID];
     if (result.isArchivedRoom) {
-        const archiveReason =
-            (lastReportActions[report.reportID] && lastReportActions[report.reportID].originalMessage && lastReportActions[report.reportID].originalMessage.reason) ||
-            CONST.REPORT.ARCHIVE_REASON.DEFAULT;
+        const archiveReason = (reportAction?.actionName === CONST.REPORT.ACTIONS.TYPE.CLOSED && reportAction?.originalMessage?.reason) || CONST.REPORT.ARCHIVE_REASON.DEFAULT;
         lastMessageText = Localize.translate(preferredLocale, `reportArchiveReasons.${archiveReason}`, {
-            displayName: archiveReason.displayName || PersonalDetailsUtils.getDisplayNameOrDefault(lastActorDetails, 'displayName'),
+            displayName: PersonalDetailsUtils.getDisplayNameOrDefault(lastActorDetails, 'displayName'),
             policyName: ReportUtils.getPolicyName(report, false, policy),
         });
     }
 
     if ((result.isChatRoom || result.isPolicyExpenseChat || result.isThread || result.isTaskReport) && !result.isArchivedRoom) {
         const lastAction = visibleReportActionItems[report.reportID];
-        if (lastAction && lastAction.actionName === CONST.REPORT.ACTIONS.TYPE.RENAMED) {
-            const newName = lodashGet(lastAction, 'originalMessage.newName', '');
+
+        if (lastAction?.actionName === CONST.REPORT.ACTIONS.TYPE.RENAMED) {
+            const newName = lastAction?.originalMessage?.newName ?? '';
             result.alternateText = Localize.translate(preferredLocale, 'newRoomPage.roomRenamedTo', {newName});
-        } else if (lastAction && lastAction.actionName === CONST.REPORT.ACTIONS.TYPE.TASKREOPENED) {
+        } else if (lastAction?.actionName === CONST.REPORT.ACTIONS.TYPE.TASKREOPENED) {
             result.alternateText = `${Localize.translate(preferredLocale, 'task.messages.reopened')}`;
-        } else if (lastAction && lastAction.actionName === CONST.REPORT.ACTIONS.TYPE.TASKCOMPLETED) {
+        } else if (lastAction?.actionName === CONST.REPORT.ACTIONS.TYPE.TASKCOMPLETED) {
             result.alternateText = `${Localize.translate(preferredLocale, 'task.messages.completed')}`;
         } else if (
-            lastAction &&
-            _.includes(
-                [
-                    CONST.REPORT.ACTIONS.TYPE.ROOMCHANGELOG.INVITE_TO_ROOM,
-                    CONST.REPORT.ACTIONS.TYPE.ROOMCHANGELOG.REMOVE_FROM_ROOM,
-                    CONST.REPORT.ACTIONS.TYPE.POLICYCHANGELOG.INVITE_TO_ROOM,
-                    CONST.REPORT.ACTIONS.TYPE.POLICYCHANGELOG.REMOVE_FROM_ROOM,
-                ],
-                lastAction.actionName,
-            )
+            lastAction?.actionName === CONST.REPORT.ACTIONS.TYPE.ROOMCHANGELOG.INVITE_TO_ROOM ||
+            lastAction?.actionName === CONST.REPORT.ACTIONS.TYPE.ROOMCHANGELOG.REMOVE_FROM_ROOM ||
+            lastAction?.actionName === CONST.REPORT.ACTIONS.TYPE.POLICYCHANGELOG.INVITE_TO_ROOM ||
+            lastAction?.actionName === CONST.REPORT.ACTIONS.TYPE.POLICYCHANGELOG.REMOVE_FROM_ROOM
         ) {
-            const targetAccountIDs = lodashGet(lastAction, 'originalMessage.targetAccountIDs', []);
+            const targetAccountIDs = lastAction?.originalMessage?.targetAccountIDs ?? [];
             const verb =
                 lastAction.actionName === CONST.REPORT.ACTIONS.TYPE.ROOMCHANGELOG.INVITE_TO_ROOM || lastAction.actionName === CONST.REPORT.ACTIONS.TYPE.POLICYCHANGELOG.INVITE_TO_ROOM
                     ? 'invited'
@@ -375,7 +448,7 @@ function getOptionData(report, reportActions, personalDetails, preferredLocale,
             const users = targetAccountIDs.length > 1 ? 'users' : 'user';
             result.alternateText = `${verb} ${targetAccountIDs.length} ${users}`;
 
-            const roomName = lodashGet(lastAction, 'originalMessage.roomName', '');
+            const roomName = lastAction?.originalMessage?.roomName ?? '';
             if (roomName) {
                 const preposition =
                     lastAction.actionName === CONST.REPORT.ACTIONS.TYPE.ROOMCHANGELOG.INVITE_TO_ROOM || lastAction.actionName === CONST.REPORT.ACTIONS.TYPE.POLICYCHANGELOG.INVITE_TO_ROOM
@@ -383,7 +456,7 @@ function getOptionData(report, reportActions, personalDetails, preferredLocale,
                         : ' from';
                 result.alternateText += `${preposition} ${roomName}`;
             }
-        } else if (lastAction && lastAction.actionName !== CONST.REPORT.ACTIONS.TYPE.REPORTPREVIEW && lastActorDisplayName && lastMessageTextFromReport) {
+        } else if (lastAction?.actionName !== CONST.REPORT.ACTIONS.TYPE.REPORTPREVIEW && lastActorDisplayName && lastMessageTextFromReport) {
             result.alternateText = `${lastActorDisplayName}: ${lastMessageText}`;
         } else {
             result.alternateText = lastAction && lastMessageTextFromReport.length > 0 ? lastMessageText : Localize.translate(preferredLocale, 'report.noActivityYet');
@@ -394,19 +467,23 @@ function getOptionData(report, reportActions, personalDetails, preferredLocale,
             // We also add a fullstop after the final name, the word "and" before the final name and commas between all previous names.
             lastMessageText =
                 Localize.translate(preferredLocale, 'reportActionsView.beginningOfChatHistory') +
-                _.map(displayNamesWithTooltips, ({displayName, pronouns}, index) => {
-                    const formattedText = _.isEmpty(pronouns) ? displayName : `${displayName} (${pronouns})`;
-
-                    if (index === displayNamesWithTooltips.length - 1) {
-                        return `${formattedText}.`;
-                    }
-                    if (index === displayNamesWithTooltips.length - 2) {
-                        return `${formattedText} ${Localize.translate(preferredLocale, 'common.and')}`;
-                    }
-                    if (index < displayNamesWithTooltips.length - 2) {
-                        return `${formattedText},`;
-                    }
-                }).join(' ');
+                displayNamesWithTooltips
+                    .map(({displayName, pronouns}, index) => {
+                        const formattedText = !pronouns ? displayName : `${displayName} (${pronouns})`;
+
+                        if (index === displayNamesWithTooltips.length - 1) {
+                            return `${formattedText}.`;
+                        }
+                        if (index === displayNamesWithTooltips.length - 2) {
+                            return `${formattedText} ${Localize.translate(preferredLocale, 'common.and')}`;
+                        }
+                        if (index < displayNamesWithTooltips.length - 2) {
+                            return `${formattedText},`;
+                        }
+
+                        return '';
+                    })
+                    .join(' ');
         }
 
         result.alternateText = lastMessageText || formattedLogin;
diff --git a/src/types/onyx/OriginalMessage.ts b/src/types/onyx/OriginalMessage.ts
index 26ccb59f4f46..cd2bf1bbbe42 100644
--- a/src/types/onyx/OriginalMessage.ts
+++ b/src/types/onyx/OriginalMessage.ts
@@ -145,7 +145,18 @@ type OriginalMessageReportPreview = {
 
 type OriginalMessagePolicyChangeLog = {
     actionName: ValueOf<typeof CONST.REPORT.ACTIONS.TYPE.POLICYCHANGELOG>;
-    originalMessage: unknown;
+    originalMessage: {
+        targetAccountIDs?: number[];
+        roomName?: string;
+    };
+};
+
+type OriginalMessageRoomChangeLog = {
+    actionName: ValueOf<typeof CONST.REPORT.ACTIONS.TYPE.ROOMCHANGELOG>;
+    originalMessage: {
+        targetAccountIDs?: number[];
+        roomName?: string;
+    };
 };
 
 type OriginalMessagePolicyTask = {
@@ -177,6 +188,7 @@ type OriginalMessage =
     | OriginalMessageRenamed
     | OriginalMessageChronosOOOList
     | OriginalMessageReportPreview
+    | OriginalMessageRoomChangeLog
     | OriginalMessagePolicyChangeLog
     | OriginalMessagePolicyTask
     | OriginalMessageModifiedExpense
diff --git a/src/types/onyx/PersonalDetails.ts b/src/types/onyx/PersonalDetails.ts
index 201273beac63..0cd264802128 100644
--- a/src/types/onyx/PersonalDetails.ts
+++ b/src/types/onyx/PersonalDetails.ts
@@ -42,6 +42,9 @@ type PersonalDetails = {
 
     /** Timezone of the current user from their personal details */
     timezone?: Timezone;
+
+    /** Status of the current user from their personal details */
+    status?: string;
 };
 
 export type {Timezone};
diff --git a/src/types/onyx/Report.ts b/src/types/onyx/Report.ts
index 8587cf9b7cd5..494661b2fb89 100644
--- a/src/types/onyx/Report.ts
+++ b/src/types/onyx/Report.ts
@@ -72,7 +72,25 @@ type Report = {
     participantAccountIDs?: number[];
     total?: number;
     currency?: string;
+
+    /** Whether the report is waiting on a bank account */
+    isWaitingOnBankAccount?: boolean;
+
+    /** Whether the last message was deleted */
+    isLastMessageDeletedParentAction?: boolean;
+
+    /** The ID of the IOU report */
+    iouReportID?: string;
+
+    /** Total amount of money owed for IOU report */
+    iouReportAmount?: number;
+
+    /** Pending fields for the report */
+    pendingFields?: Record<string, OnyxCommon.PendingAction>;
+
+    /** The ID of the preexisting report (it is possible that we optimistically created a Report for which a report already exists) */
     preexistingReportID?: string;
+
     /** If the report contains nonreimbursable expenses, send the nonreimbursable total */
     nonReimbursableTotal?: number;
 };
diff --git a/src/types/onyx/ReportAction.ts b/src/types/onyx/ReportAction.ts
index fbe4c02c4072..19908273ad3d 100644
--- a/src/types/onyx/ReportAction.ts
+++ b/src/types/onyx/ReportAction.ts
@@ -75,9 +75,6 @@ type ReportActionBase = {
     /** Whether we have received a response back from the server */
     isLoading?: boolean;
 
-    /** Error message that's come back from the server. */
-    error?: string;
-
     /** accountIDs of the people to which the whisper was sent to (if any). Returns empty array if it is not a whisper */
     whisperedToAccountIDs?: number[];
 
