Skip to content

Commit

Permalink
Clean up SearchRouterList item types
Browse files Browse the repository at this point in the history
  • Loading branch information
Kicu committed Sep 25, 2024
1 parent 445a031 commit e9e14f3
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 23 deletions.
24 changes: 14 additions & 10 deletions src/components/Search/SearchRouter/SearchRouterList.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import React, {useCallback} from 'react';
import * as Expensicons from '@components/Icon/Expensicons';
import type {SearchQueryJSON, SearchRouterListItem} from '@components/Search/types';
import type {SearchQueryJSON} from '@components/Search/types';
import SelectionList from '@components/SelectionList';
import SingleIconListItem from '@components/SelectionList/Search/SingleIconListItem';
import type {ListItemWithSingleIcon, SingleIconListItemProps} from '@components/SelectionList/Search/SingleIconListItem';
import type {SectionListDataType, UserListItemProps} from '@components/SelectionList/types';
import type {SingleIconListItemProps} from '@components/SelectionList/Search/SingleIconListItem';
import type {SectionListDataType, SingleIconListItemType, UserListItemProps, UserListItemType} from '@components/SelectionList/types';
import UserListItem from '@components/SelectionList/UserListItem';
import useLocalize from '@hooks/useLocalize';
import useThemeStyles from '@hooks/useThemeStyles';
Expand All @@ -29,25 +29,28 @@ type SearchRouterListProps = {
closeAndClearRouter: () => void;
};

function SearchRouterItem(props: UserListItemProps<SearchRouterListItem> | SingleIconListItemProps<SearchRouterListItem>) {
function SearchRouterItem(props: UserListItemProps<UserListItemType> | SingleIconListItemProps<SingleIconListItemType>) {
const styles = useThemeStyles();
if (props.item.itemType === CONST.SEARCH.ROUTER_LIST_ITEM_TYPE.REPORT) {
// Here instead of checking itemType prepare correct type guards for the prop types and use them
if (props.item) {
// this cast would actually happen in the type guard; type guard can stay in this file I think
const actuallyProps = props as UserListItemProps<UserListItemType>;
return (
<UserListItem
pressableStyle={styles.br2}
// eslint-disable-next-line react/jsx-props-no-spreading
{...(props as UserListItemProps<OptionData>)}
{...actuallyProps}
/>
);
}
// eslint-disable-next-line react/jsx-props-no-spreading
return <SingleIconListItem {...(props as SingleIconListItemProps<ListItemWithSingleIcon & ItemWithQuery>)} />;
return <SingleIconListItem {...props} />;

Check failure on line 47 in src/components/Search/SearchRouter/SearchRouterList.tsx

View workflow job for this annotation

GitHub Actions / typecheck

Type '{ isFocused?: boolean | undefined; isDisabled?: boolean | null | undefined; showTooltip?: boolean | undefined; canSelectMultiple?: boolean | undefined; onSelectRow: (item: UserListItemType) => void; ... 22 more ...; FooterComponent?: ReactElement<...> | undefined; } | { ...; }' is not assignable to type 'IntrinsicAttributes & SingleIconListItemProps<SingleIconListItemType>'.
}

function SearchRouterList({currentQuery, reportForContextualSearch, recentSearches, recentReports, onSearchSubmit, updateUserSearchQuery, closeAndClearRouter}: SearchRouterListProps) {
const styles = useThemeStyles();
const {translate} = useLocalize();
const sections: Array<SectionListDataType<SearchRouterListItem>> = [];
const sections: Array<SectionListDataType<SingleIconListItemType | UserListItemType>> = [];

if (currentQuery?.inputQuery) {
sections.push({
Expand Down Expand Up @@ -95,8 +98,9 @@ function SearchRouterList({currentQuery, reportForContextualSearch, recentSearch
sections.push({title: translate('search.recentChats'), data: recentReportsData});

Check failure on line 98 in src/components/Search/SearchRouter/SearchRouterList.tsx

View workflow job for this annotation

GitHub Actions / typecheck

Type '{ pressableStyle: { borderRadius: number; }; itemType: "report"; text?: string | undefined; alternateText?: string | undefined; allReportErrors?: Errors | undefined; brickRoadIndicator?: "" | ... 2 more ... | undefined; ... 119 more ...; pendingFields?: PendingFields<...> | undefined; }[]' is not assignable to type 'readonly (UserListItemType | SingleIconListItemType)[] & (UserListItemType | SingleIconListItemType)[]'.

const onSelectRow = useCallback(
(item: SearchRouterListItem) => {
(item: SingleIconListItemType | UserListItemType) => {
// eslint-disable-next-line default-case
// Here instead of switch on itemType prepare correct type guards for the types of list item: SingleIconListItemType and UserListItemType and use them here
switch (item.itemType) {

Check failure on line 104 in src/components/Search/SearchRouter/SearchRouterList.tsx

View workflow job for this annotation

GitHub Actions / ESLint check

Expected a default case

Check failure on line 104 in src/components/Search/SearchRouter/SearchRouterList.tsx

View workflow job for this annotation

GitHub Actions / typecheck

Property 'itemType' does not exist on type 'UserListItemType | SingleIconListItemType'. Did you mean 'itemStyle'?

Check failure on line 104 in src/components/Search/SearchRouter/SearchRouterList.tsx

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Expected a default case
case CONST.SEARCH.ROUTER_LIST_ITEM_TYPE.SEARCH:
// Handle selection of "Recent search"
Expand Down Expand Up @@ -126,7 +130,7 @@ function SearchRouterList({currentQuery, reportForContextualSearch, recentSearch
);

return (
<SelectionList<SearchRouterListItem>
<SelectionList<SingleIconListItemType | UserListItemType>
sections={sections}
onSelectRow={onSelectRow}
ListItem={SearchRouterItem}
Expand Down
6 changes: 0 additions & 6 deletions src/components/Search/types.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import type {ValueOf} from 'react-native-gesture-handler/lib/typescript/typeUtils';
import type {ListItemWithSingleIcon} from '@components/SelectionList/Search/SingleIconListItem';
import type {OptionData} from '@libs/ReportUtils';
import type CONST from '@src/CONST';
import type {SearchDataTypes} from '@src/types/onyx/SearchResults';
import type {ItemWithQuery} from './SearchRouter/SearchRouterList';

/** Model of the selected transaction */
type SelectedTransactionInfo = {
Expand Down Expand Up @@ -76,8 +73,6 @@ type SearchQueryJSON = {
flatFilters: QueryFilters;
} & SearchQueryAST;

type SearchRouterListItem = (OptionData | (ListItemWithSingleIcon & ItemWithQuery)) & {itemType?: ValueOf<typeof CONST.SEARCH.ROUTER_LIST_ITEM_TYPE>};

export type {
SelectedTransactionInfo,
SelectedTransactions,
Expand All @@ -96,5 +91,4 @@ export type {
InvoiceSearchStatus,
TripSearchStatus,
ChatSearchStatus,
SearchRouterListItem,
};
11 changes: 4 additions & 7 deletions src/components/SelectionList/Search/SingleIconListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,20 @@ import React from 'react';
import {View} from 'react-native';
import Icon from '@components/Icon';
import BaseListItem from '@components/SelectionList/BaseListItem';
import type {ListItem} from '@components/SelectionList/types';
import type {ListItem, SingleIconListItemType} from '@components/SelectionList/types';
import TextWithTooltip from '@components/TextWithTooltip';
import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import type IconAsset from '@src/types/utils/IconAsset';

type ListItemWithSingleIcon = {singleIcon?: IconAsset} & ListItem;

type SingleIconListItemProps<TItem extends ListItemWithSingleIcon> = {
type SingleIconListItemProps<TItem extends ListItem> = {
item: TItem;
isFocused?: boolean;
showTooltip?: boolean;
onSelectRow: (item: TItem) => void;
onFocus?: () => void;
};

function SingleIconListItem<TItem extends ListItemWithSingleIcon>({item, isFocused, showTooltip, onSelectRow, onFocus}: SingleIconListItemProps<TItem>) {
function SingleIconListItem<TItem extends SingleIconListItemType>({item, isFocused, showTooltip, onSelectRow, onFocus}: SingleIconListItemProps<TItem>) {
const styles = useThemeStyles();
const theme = useTheme();

Expand Down Expand Up @@ -71,4 +68,4 @@ function SingleIconListItem<TItem extends ListItemWithSingleIcon>({item, isFocus
SingleIconListItem.displayName = 'SingleIconListItem';

export default SingleIconListItem;
export type {ListItemWithSingleIcon, SingleIconListItemProps};
export type {SingleIconListItemProps};
15 changes: 15 additions & 0 deletions src/components/SelectionList/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type {MutableRefObject, ReactElement, ReactNode} from 'react';
import type {GestureResponderEvent, InputModeOptions, LayoutChangeEvent, SectionListData, StyleProp, TextInput, TextStyle, ViewStyle} from 'react-native';
import type {SearchRouterItem} from '@components/Search/SearchRouter/SearchRouterList';
import type {SearchQueryString} from '@components/Search/types';
import type {BrickRoad} from '@libs/WorkspacesSettingsUtils';
// eslint-disable-next-line no-restricted-imports
import type CursorStyles from '@styles/utils/cursor/types';
Expand Down Expand Up @@ -241,6 +242,18 @@ type ReportListItemType = ListItem &
transactions: TransactionListItemType[];
};

type UserListItemType = ListItem & {
foo: string;
};

// In general I don't think we can create a generic `SingleIconListItemType` if you want to store query in it
// Im afraid we might just name it properly like SomethingSomethingSearchItem...
type SingleIconListItemType = ListItem & {
singleIcon?: IconAsset;
query: SearchQueryString;
itemType: string; // fix this
};

type ListItemProps<TItem extends ListItem> = CommonListItemProps<TItem> & {
/** The section list item */
item: TItem;
Expand Down Expand Up @@ -600,6 +613,8 @@ export type {
TransactionListItemProps,
TransactionListItemType,
UserListItemProps,
UserListItemType,
SingleIconListItemType,
ValidListItem,
ReportActionListItemType,
ChatListItemProps,
Expand Down

0 comments on commit e9e14f3

Please sign in to comment.