From 09697215c41a7e374915bca81ab03bc357e4db1b Mon Sep 17 00:00:00 2001 From: hidden4003 Date: Thu, 21 Sep 2023 13:11:39 +0300 Subject: [PATCH 1/3] Add @typescript-eslint/no-explicit-any (issue #626) --- .eslintrc.json | 1 + .../BackgroundImagePlaceholderDiv.tsx | 2 +- src/components/CharacterImage.tsx | 2 +- src/components/Dialogs/ActionsModal.tsx | 10 +++-- src/components/Dialogs/ImportFolderModal.tsx | 30 ++++++++----- src/components/Dialogs/LanguagesModal.tsx | 2 +- src/components/Input/Button.tsx | 4 +- src/components/Input/Checkbox.tsx | 2 +- src/components/Input/Input.tsx | 6 +-- src/components/Input/InputSmall.tsx | 4 +- src/components/Input/Select.tsx | 4 +- src/components/Input/SelectEpisodeList.tsx | 4 +- src/components/Input/SelectSmall.tsx | 4 +- src/components/Layout/MenuItem.tsx | 2 +- src/components/Panels/ModalPanel.tsx | 2 +- src/components/Panels/ShokoPanel.tsx | 4 +- src/components/TransitionDiv.tsx | 2 +- .../Utilities/Unrecognized/MenuButton.tsx | 2 +- src/components/Utilities/UtilitiesTable.tsx | 2 +- src/core/localStorage.ts | 6 +-- src/core/middlewares/rtkQueryError.ts | 2 +- src/core/rtkQuery/externalApi.ts | 2 +- src/core/rtkQuery/splitV3Api/seriesApi.ts | 4 +- src/core/slices/firstrun.ts | 2 +- src/core/slices/misc.ts | 4 +- src/core/util.ts | 44 ++++++++++++------- src/pages/dashboard/panels/MediaType.tsx | 4 +- src/pages/error/ErrorPage.tsx | 2 +- src/pages/firstrun/AniDBAccount.tsx | 2 +- src/pages/firstrun/ImportFolders.tsx | 10 +++-- .../firstrun/MetadataSourcesTabs/AniDBTab.tsx | 2 +- .../MetadataSourcesTabs/MovieDBTab.tsx | 2 +- .../firstrun/MetadataSourcesTabs/TvDBTab.tsx | 2 +- src/pages/settings/tabs/GeneralSettings.tsx | 3 +- .../utilities/SeriesWithoutFilesUtility.tsx | 7 ++- src/pages/utilities/UnrecognizedUtility.tsx | 1 + 36 files changed, 112 insertions(+), 76 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index dd7cb2675..42618b11f 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -45,6 +45,7 @@ "error", "type" ], + "@typescript-eslint/no-explicit-any": "error", "arrow-parens": [ "error", "as-needed", diff --git a/src/components/BackgroundImagePlaceholderDiv.tsx b/src/components/BackgroundImagePlaceholderDiv.tsx index d33a247f3..a65b674a8 100644 --- a/src/components/BackgroundImagePlaceholderDiv.tsx +++ b/src/components/BackgroundImagePlaceholderDiv.tsx @@ -6,7 +6,7 @@ import cx from 'classnames'; import type { ImageType } from '@/core/types/api/common'; type Props = { - children?: any; + children?: React.ReactNode; className?: string; image: ImageType | null; hidePlaceholderOnHover?: boolean; diff --git a/src/components/CharacterImage.tsx b/src/components/CharacterImage.tsx index 8a45d164b..ac205ab3c 100644 --- a/src/components/CharacterImage.tsx +++ b/src/components/CharacterImage.tsx @@ -4,7 +4,7 @@ import { Icon } from '@mdi/react'; import cx from 'classnames'; type Props = { - children?: any; + children?: React.ReactNode; className?: string; imageSrc: string | null; hidePlaceholderOnHover?: boolean; diff --git a/src/components/Dialogs/ActionsModal.tsx b/src/components/Dialogs/ActionsModal.tsx index 239bdc7b5..f4196603a 100644 --- a/src/components/Dialogs/ActionsModal.tsx +++ b/src/components/Dialogs/ActionsModal.tsx @@ -11,6 +11,7 @@ import toast from '@/components/Toast'; import TransitionDiv from '@/components/TransitionDiv'; import quickActions from '@/core/quick-actions'; import { useRunActionMutation } from '@/core/rtkQuery/splitV3Api/actionsApi'; +import { isErrorWithMessage } from '@/core/util'; const actions = { import: { @@ -89,10 +90,13 @@ const Action = ({ actionKey }: { actionKey: string }) => { const [runActionTrigger] = useRunActionMutation(); const runAction = async (name: string, action) => { - // TODO: figure out better type for this - const result: any = await runActionTrigger(action); - if (!result.error) { + try { + await runActionTrigger(action); toast.success(`Running action "${name}"`); + } catch (err) { + if (isErrorWithMessage(err)) { + console.error(err.message); + } } }; diff --git a/src/components/Dialogs/ImportFolderModal.tsx b/src/components/Dialogs/ImportFolderModal.tsx index 371c22006..3e98376d9 100644 --- a/src/components/Dialogs/ImportFolderModal.tsx +++ b/src/components/Dialogs/ImportFolderModal.tsx @@ -16,6 +16,7 @@ import { } from '@/core/rtkQuery/splitV3Api/importFolderApi'; import { setStatus as setBrowseStatus } from '@/core/slices/modals/browseFolder'; import { setStatus } from '@/core/slices/modals/importFolder'; +import { isErrorWithMessage } from '@/core/util'; import BrowseFolderModal from './BrowseFolderModal'; @@ -53,7 +54,7 @@ function ImportFolderModal() { } }; - const handleInputChange = (event: any) => { + const handleInputChange = (event: React.ChangeEvent) => { const name = event.target.id; const value = name === 'WatchForNewFiles' ? event.target.value === '1' : event.target.value; setImportFolder({ ...importFolder, [name]: value }); @@ -62,28 +63,37 @@ function ImportFolderModal() { const handleBrowse = () => dispatch(setBrowseStatus(true)); const handleClose = () => dispatch(setStatus(false)); const handleDelete = async () => { - // TODO: can this be better typed? - const result: any = await deleteFolder({ folderId: ID }); - if (!result.error) { + try { + await deleteFolder({ folderId: ID }).unwrap(); toast.success('Import folder deleted!'); dispatch(setStatus(false)); + } catch (err) { + if (isErrorWithMessage(err)) { + console.error(err.message); + } } }; const handleSave = async () => { - // TODO: can this be better typed? - let result; if (edit) { - result = await updateFolder(importFolder); - if (!result.error) { + try { + await updateFolder(importFolder); toast.success('Import folder edited!'); dispatch(setStatus(false)); + } catch (err) { + if (isErrorWithMessage(err)) { + console.error(err.message); + } } } else { - result = await createFolder(importFolder); - if (!result.error) { + try { + await createFolder(importFolder); toast.success('Import folder added!'); dispatch(setStatus(false)); + } catch (err) { + if (isErrorWithMessage(err)) { + console.error(err.message); + } } } }; diff --git a/src/components/Dialogs/LanguagesModal.tsx b/src/components/Dialogs/LanguagesModal.tsx index 7d6095acd..2116363e2 100644 --- a/src/components/Dialogs/LanguagesModal.tsx +++ b/src/components/Dialogs/LanguagesModal.tsx @@ -94,7 +94,7 @@ function LanguagesModal({ onClose, type }: Props) { if (type !== null) setLanguages(LanguagePreference); }, [type, LanguagePreference]); - const handleInputChange = (event: any) => { + const handleInputChange = (event) => { const { checked: value, id } = event.target; const newLanguages = languages.slice(); diff --git a/src/components/Input/Button.tsx b/src/components/Input/Button.tsx index 097864177..83a70a10a 100644 --- a/src/components/Input/Button.tsx +++ b/src/components/Input/Button.tsx @@ -6,11 +6,11 @@ import cx from 'classnames'; type Props = { buttonType?: string; className?: string; - children: any; + children: React.ReactNode; disabled?: boolean; loading?: boolean; loadingSize?: number; - onClick?: (...args: any) => void; + onClick?: React.MouseEventHandler; submit?: boolean; tooltip?: string; }; diff --git a/src/components/Input/Checkbox.tsx b/src/components/Input/Checkbox.tsx index c1fa9bad2..8042b8037 100644 --- a/src/components/Input/Checkbox.tsx +++ b/src/components/Input/Checkbox.tsx @@ -13,7 +13,7 @@ type Props = { className?: string; labelRight?: boolean; justify?: boolean; - onChange: (event: any) => void; + onChange: React.ChangeEventHandler; }; function Checkbox({ className, id, intermediate, isChecked, justify, label, labelRight, onChange }: Props) { diff --git a/src/components/Input/Input.tsx b/src/components/Input/Input.tsx index b0747b04c..ab3b5f61a 100644 --- a/src/components/Input/Input.tsx +++ b/src/components/Input/Input.tsx @@ -8,15 +8,15 @@ type Props = { type: string; placeholder?: string; value: string | number; - onChange: (event: any) => void; - onKeyUp?: (event: any) => void; + onChange: React.ChangeEventHandler; + onKeyUp?: React.KeyboardEventHandler; className?: string; inputClassName?: string; autoFocus?: boolean; disabled?: boolean; center?: boolean; endIcon?: string; - endIconClick?: (event: any) => void; + endIconClick?: React.MouseEventHandler; startIcon?: string; inline?: boolean; }; diff --git a/src/components/Input/InputSmall.tsx b/src/components/Input/InputSmall.tsx index 7fa8288fa..bfcf0e5c9 100644 --- a/src/components/Input/InputSmall.tsx +++ b/src/components/Input/InputSmall.tsx @@ -5,8 +5,8 @@ type Props = { type: string; placeholder?: string; value: string | number; - onChange: (event: any) => void; - onKeyUp?: (event: any) => void; + onChange: React.ChangeEventHandler; + onKeyUp?: React.KeyboardEventHandler; className?: string; autoFocus?: boolean; disabled?: boolean; diff --git a/src/components/Input/Select.tsx b/src/components/Input/Select.tsx index 4cea660ce..099159ba7 100644 --- a/src/components/Input/Select.tsx +++ b/src/components/Input/Select.tsx @@ -5,9 +5,9 @@ import { Icon } from '@mdi/react'; type Props = { id: string; value: string | number; - onChange: (event: any) => void; + onChange: React.ChangeEventHandler; className?: string; - children: any; + children: React.ReactNode; label?: string; }; diff --git a/src/components/Input/SelectEpisodeList.tsx b/src/components/Input/SelectEpisodeList.tsx index 46a0920af..20652c7e0 100644 --- a/src/components/Input/SelectEpisodeList.tsx +++ b/src/components/Input/SelectEpisodeList.tsx @@ -98,8 +98,8 @@ const SelectEpisodeList = ( ) => { const [epFilter, setEpFilter] = useState(0); const [selected, setSelected] = useState(options[0]); - const [portalEl, setPortalEl] = useState(null as any); - const [displayNode, setDisplayNode] = React.useState(null as any); + const [portalEl, setPortalEl] = useState(null); + const [displayNode, setDisplayNode] = React.useState(null); const displayRef = useRef(null); const buttonRef = useRef(null); diff --git a/src/components/Input/SelectSmall.tsx b/src/components/Input/SelectSmall.tsx index 1c68a7657..c8221ade5 100644 --- a/src/components/Input/SelectSmall.tsx +++ b/src/components/Input/SelectSmall.tsx @@ -5,9 +5,9 @@ import { Icon } from '@mdi/react'; type Props = { id: string; value: string | number; - onChange: (event: any) => void; + onChange: React.ChangeEventHandler; className?: string; - children: any; + children: React.ReactNode; label?: string; }; diff --git a/src/components/Layout/MenuItem.tsx b/src/components/Layout/MenuItem.tsx index 047dab3fe..b62348eda 100644 --- a/src/components/Layout/MenuItem.tsx +++ b/src/components/Layout/MenuItem.tsx @@ -32,7 +32,7 @@ export type MenuItemProps = { icon: IconType; label: string; className?: string; - onClick: (event: any) => void; + onClick: React.MouseEventHandler; }; function MenuItem(props: MenuItemProps) { diff --git a/src/components/Panels/ModalPanel.tsx b/src/components/Panels/ModalPanel.tsx index c03fce166..c2f7cb776 100644 --- a/src/components/Panels/ModalPanel.tsx +++ b/src/components/Panels/ModalPanel.tsx @@ -3,7 +3,7 @@ import Modal from 'react-modal'; import cx from 'classnames'; type Props = { - children: any; + children: React.ReactNode; show: boolean; title: React.ReactNode; size?: 'sm' | 'md' | 'lg'; diff --git a/src/components/Panels/ShokoPanel.tsx b/src/components/Panels/ShokoPanel.tsx index f95029323..73778ebbb 100644 --- a/src/components/Panels/ShokoPanel.tsx +++ b/src/components/Panels/ShokoPanel.tsx @@ -5,8 +5,8 @@ import cx from 'classnames'; type Props = { title: ReactNode; - children: any; - options?: any; + children: React.ReactNode; + options?: React.ReactNode; className?: string; isFetching?: boolean; editMode?: boolean; diff --git a/src/components/TransitionDiv.tsx b/src/components/TransitionDiv.tsx index 1419033d3..610cfd190 100644 --- a/src/components/TransitionDiv.tsx +++ b/src/components/TransitionDiv.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { Transition } from '@headlessui/react'; type Props = { - children: any; + children: React.ReactNode; className?: string; enter?: string; enterFrom?: string; diff --git a/src/components/Utilities/Unrecognized/MenuButton.tsx b/src/components/Utilities/Unrecognized/MenuButton.tsx index ce2f20e3b..395fcdc1b 100644 --- a/src/components/Utilities/Unrecognized/MenuButton.tsx +++ b/src/components/Utilities/Unrecognized/MenuButton.tsx @@ -6,7 +6,7 @@ import Button from '@/components/Input/Button'; const MenuButton = ( { disabled, highlight = false, icon, name, onClick }: { - onClick: (...args: any) => void; + onClick: React.MouseEventHandler; icon: string; name: string; highlight?: boolean; diff --git a/src/components/Utilities/UtilitiesTable.tsx b/src/components/Utilities/UtilitiesTable.tsx index c1057df85..40599d377 100644 --- a/src/components/Utilities/UtilitiesTable.tsx +++ b/src/components/Utilities/UtilitiesTable.tsx @@ -57,7 +57,7 @@ function UtilitiesTable(props: Props) { const lrIndex = lastRowSelected?.current?.index ?? row.index; const fromIndex = Math.min(lrIndex, row.index); const toIndex = Math.max(lrIndex, row.index); - const rowSelection: any = {}; + const rowSelection = {}; for (let i = fromIndex; i <= toIndex; i += 1) { rowSelection[i] = lastRowSelected.current?.getIsSelected() ?? true; } diff --git a/src/core/localStorage.ts b/src/core/localStorage.ts index 5d0b90c13..e44df4031 100644 --- a/src/core/localStorage.ts +++ b/src/core/localStorage.ts @@ -18,16 +18,16 @@ export const loadState = (): RootState => { const serializedState = JSON.parse(globalThis.sessionStorage.getItem('state') ?? '{}'); const apiSessionString = globalThis.localStorage.getItem('apiSession'); if (apiSessionString === null) { - return checkVersion(get(serializedState, 'apiSession.version', '')) ? serializedState : {} as any; + return checkVersion(get(serializedState, 'apiSession.version', '')) ? serializedState : {} as RootState; } const apiSession = JSON.parse(apiSessionString); if (!checkVersion(get(apiSession, 'version', ''))) { globalThis.localStorage.clear(); - return {} as any; + return {} as RootState; } return { ...serializedState, apiSession }; } catch (err) { - return ({} as any); + return ({} as RootState); } }; diff --git a/src/core/middlewares/rtkQueryError.ts b/src/core/middlewares/rtkQueryError.ts index d37c6ffdb..9341017df 100644 --- a/src/core/middlewares/rtkQueryError.ts +++ b/src/core/middlewares/rtkQueryError.ts @@ -14,7 +14,7 @@ type ProblemDetails = { traceId: string; }; -const isErrorObject = (target: any): target is ProblemDetails => +const isErrorObject = (target): target is ProblemDetails => typeof target === 'object' && target !== null && typeof target.title === 'string' && typeof target.errors === 'object' && target.errors !== null; diff --git a/src/core/rtkQuery/externalApi.ts b/src/core/rtkQuery/externalApi.ts index 10498853e..a9c212ef9 100644 --- a/src/core/rtkQuery/externalApi.ts +++ b/src/core/rtkQuery/externalApi.ts @@ -10,7 +10,7 @@ export const externalApi = createApi({ // Get blog posts from shokoanime.com getShokoNewsFeed: build.query, void>({ query: () => ({ url: 'https://shokoanime.com/jsonfeed/index.json' }), - transformResponse: (response: any) => response.items ?? [], + transformResponse: (response: { items?: DashboardNewsType[] }) => response.items ?? [], }), }), }); diff --git a/src/core/rtkQuery/splitV3Api/seriesApi.ts b/src/core/rtkQuery/splitV3Api/seriesApi.ts index 32f617770..fb9562f81 100644 --- a/src/core/rtkQuery/splitV3Api/seriesApi.ts +++ b/src/core/rtkQuery/splitV3Api/seriesApi.ts @@ -62,7 +62,7 @@ const seriesApi = splitV3Api.injectEndpoints({ // Search the title dump for the given query or directly using the anidb id. getSeriesAniDBSearch: build.query, { query: string } & PaginationType>({ query: ({ query, ...params }) => ({ url: `Series/AniDB/Search/${encodeURIComponent(query)}`, params }), - transformResponse: (response: any) => response.List, + transformResponse: (response: ListResultType>) => response.List, providesTags: ['SeriesSearch'], }), @@ -132,7 +132,7 @@ const seriesApi = splitV3Api.injectEndpoints({ // Gets anidb recommendation for the user getAniDBRecommendedAnime: build.query, PaginationType>({ query: params => ({ url: 'Series/AniDB/RecommendedForYou', params: { ...params, showAll: true } }), - transformResponse: (response: any) => response.List, + transformResponse: (response: ListResultType>) => response.List, }), getSeriesWithManuallyLinkedFiles: build.query>, PaginationType>({ diff --git a/src/core/slices/firstrun.ts b/src/core/slices/firstrun.ts index 2241c1a0f..9bfb01436 100644 --- a/src/core/slices/firstrun.ts +++ b/src/core/slices/firstrun.ts @@ -27,7 +27,7 @@ const firstrunSlice = createSlice({ setSaved(sliceState, action: PayloadAction) { sliceState.saved = Object.assign({}, sliceState.saved, { [action.payload]: true }); }, - setUser(sliceState, action: PayloadAction) { + setUser(sliceState, action: PayloadAction) { sliceState.user = Object.assign({}, sliceState.user, action.payload); }, unsetSaved(sliceState, action: PayloadAction) { diff --git a/src/core/slices/misc.ts b/src/core/slices/misc.ts index 9775126bc..003712075 100644 --- a/src/core/slices/misc.ts +++ b/src/core/slices/misc.ts @@ -15,9 +15,9 @@ const miscSlice = createSlice({ }, webuiUpdateAvailable: false, webuiPreviewTheme: null, - } as any, + }, reducers: { - setItem(sliceState, action: PayloadAction) { + setItem(sliceState, action: PayloadAction) { return Object.assign({}, sliceState, action.payload); }, }, diff --git a/src/core/util.ts b/src/core/util.ts index 65b9346a8..81dfee9d1 100644 --- a/src/core/util.ts +++ b/src/core/util.ts @@ -3,8 +3,9 @@ import { compareItems, rankItem } from '@tanstack/match-sorter-utils'; import { sortingFns } from '@tanstack/react-table'; import copy from 'copy-to-clipboard'; import formatThousands from 'format-thousands'; -import { each, isObject, unset } from 'lodash'; +import { isObject } from 'lodash'; +import type { FetchBaseQueryError } from '@reduxjs/toolkit/query'; import type { RankingInfo } from '@tanstack/match-sorter-utils'; import type { FilterFn, SortingFn } from '@tanstack/react-table'; @@ -37,20 +38,6 @@ export function mergeDeep(...objects) { }, {}); } -// Needed to compare layout properties. -// Stolen from https://stackoverflow.com/questions/37246775/ -export function omitDeepBy(value: any, iteratee: Function) { - each(value, (v, k) => { - if (iteratee(v, k)) { - unset(value, k); - } else if (isObject(v)) { - omitDeepBy(v, iteratee); - } - }); - - return value; -} - // tanstack table helpers declare module '@tanstack/table-core' { @@ -64,13 +51,13 @@ declare module '@tanstack/table-core' { } } -export const fuzzyFilter: FilterFn = (row, columnId, value, addMeta) => { +export const fuzzyFilter: FilterFn<{}> = (row, columnId, value, addMeta) => { const itemRank = rankItem(row.getValue(columnId), value); addMeta({ itemRank }); return itemRank.passed; }; -export const fuzzySort: SortingFn = (rowA, rowB, columnId) => { +export const fuzzySort: SortingFn<{}> = (rowA, rowB, columnId) => { let dir = 0; if (rowA.columnFiltersMeta[columnId]) { dir = compareItems( @@ -96,4 +83,27 @@ export const copyToClipboard = async (text: string) => { } }; +/** + * Type predicate to narrow an unknown error to `FetchBaseQueryError` + */ +export function isFetchBaseQueryError( + error: unknown, +): error is FetchBaseQueryError { + return typeof error === 'object' && error != null && 'status' in error; +} + +/** + * Type predicate to narrow an unknown error to an object with a string 'message' property + */ +export function isErrorWithMessage( + error: unknown, +): error is { message: string } { + return ( + typeof error === 'object' + && error != null + && 'message' in error + && typeof (error as Error).message === 'string' + ); +} + export default {}; diff --git a/src/pages/dashboard/panels/MediaType.tsx b/src/pages/dashboard/panels/MediaType.tsx index 56ff81a37..719d64d2e 100644 --- a/src/pages/dashboard/panels/MediaType.tsx +++ b/src/pages/dashboard/panels/MediaType.tsx @@ -55,11 +55,11 @@ function MediaType() { ); let total = 0; - const seriesSummaryArray: Array = []; + const seriesSummaryArray: Array<[string, number]> = []; forEach(seriesSummary.data, (item, key) => { total += item ?? 0; - seriesSummaryArray.push([key, item]); + seriesSummaryArray.push([key, item ?? 0]); }); seriesSummaryArray.sort((a, b) => (a[1] < b[1] ? 1 : -1)); diff --git a/src/pages/error/ErrorPage.tsx b/src/pages/error/ErrorPage.tsx index 91b24b639..6fc13b8c9 100644 --- a/src/pages/error/ErrorPage.tsx +++ b/src/pages/error/ErrorPage.tsx @@ -3,7 +3,7 @@ import { Link, useNavigate } from 'react-router-dom'; import * as Sentry from '@sentry/react'; type Props = { - children?: any; + children?: React.ReactNode; }; const Fallback = ({ componentStack, error }) => { diff --git a/src/pages/firstrun/AniDBAccount.tsx b/src/pages/firstrun/AniDBAccount.tsx index 85c9b9ea2..5906957b6 100644 --- a/src/pages/firstrun/AniDBAccount.tsx +++ b/src/pages/firstrun/AniDBAccount.tsx @@ -27,7 +27,7 @@ function AniDBAccount() { const { Password, Username } = newSettings.AniDb; - const handleInputChange = (event: any) => { + const handleInputChange = (event) => { const { id, value } = event.target; updateSetting('AniDb', id, value); setAnidbStatus({ type: 'success', text: '' }); diff --git a/src/pages/firstrun/ImportFolders.tsx b/src/pages/firstrun/ImportFolders.tsx index 2531a4ea0..a389bcde7 100644 --- a/src/pages/firstrun/ImportFolders.tsx +++ b/src/pages/firstrun/ImportFolders.tsx @@ -13,6 +13,7 @@ import { setEdit as setImportFolderModalEdit, setStatus as setImportFolderModalStatus, } from '@/core/slices/modals/importFolder'; +import { isErrorWithMessage } from '@/core/util'; import Footer from './Footer'; @@ -31,10 +32,13 @@ const Folder = (props: ImportFolderType) => { const [deleteFolder] = useDeleteImportFolderMutation(); const handleDeleteFolder = async (folderId) => { - // TODO: can this be better typed? - const result: any = await deleteFolder({ folderId }); - if (!result.error) { + try { + await deleteFolder({ folderId }); toast.success('Import folder deleted!'); + } catch (err) { + if (isErrorWithMessage(err)) { + console.error(err.message); + } } }; diff --git a/src/pages/firstrun/MetadataSourcesTabs/AniDBTab.tsx b/src/pages/firstrun/MetadataSourcesTabs/AniDBTab.tsx index 1a521a253..ccd34280a 100644 --- a/src/pages/firstrun/MetadataSourcesTabs/AniDBTab.tsx +++ b/src/pages/firstrun/MetadataSourcesTabs/AniDBTab.tsx @@ -37,7 +37,7 @@ function AniDBTab({ setStatus }: Props) { MyListStats_UpdateFrequency, } = newSettings.AniDb; - const handleInputChange = (event: any) => { + const handleInputChange = (event) => { const { id } = event.target; const value = event.target.type === 'checkbox' ? event.target.checked : event.target.value; updateSetting('AniDb', id, value); diff --git a/src/pages/firstrun/MetadataSourcesTabs/MovieDBTab.tsx b/src/pages/firstrun/MetadataSourcesTabs/MovieDBTab.tsx index 5f18187de..3b734e55c 100644 --- a/src/pages/firstrun/MetadataSourcesTabs/MovieDBTab.tsx +++ b/src/pages/firstrun/MetadataSourcesTabs/MovieDBTab.tsx @@ -11,7 +11,7 @@ function MovieDBTab() { const { AutoFanart, AutoFanartAmount, AutoPosters, AutoPostersAmount } = newSettings.MovieDb; - const handleInputChange = (event: any) => { + const handleInputChange = (event) => { const propId = event.target.id.replace('MovieDB_', ''); const value = event.target.type === 'checkbox' ? event.target.checked : event.target.value; updateSetting('MovieDb', propId, value); diff --git a/src/pages/firstrun/MetadataSourcesTabs/TvDBTab.tsx b/src/pages/firstrun/MetadataSourcesTabs/TvDBTab.tsx index 4b97ac8aa..bcb3f79a8 100644 --- a/src/pages/firstrun/MetadataSourcesTabs/TvDBTab.tsx +++ b/src/pages/firstrun/MetadataSourcesTabs/TvDBTab.tsx @@ -11,7 +11,7 @@ import { tvdbLanguages } from '@/pages/settings/tabs/MetadataSitesSettings'; function TvDBTab() { const { newSettings, updateSetting } = useFirstRunSettingsContext(); - const handleInputChange = (event: any) => { + const handleInputChange = (event) => { const propId = event.target.id.replace('TvDB_', ''); const value = event.target.type === 'checkbox' ? event.target.checked : event.target.value; updateSetting('TvDB', propId, value); diff --git a/src/pages/settings/tabs/GeneralSettings.tsx b/src/pages/settings/tabs/GeneralSettings.tsx index bb6b2b8e8..4d53cbeb9 100644 --- a/src/pages/settings/tabs/GeneralSettings.tsx +++ b/src/pages/settings/tabs/GeneralSettings.tsx @@ -1,5 +1,6 @@ /* eslint-disable @typescript-eslint/naming-convention */ import React, { useMemo } from 'react'; +import type { ChangeEvent } from 'react'; import { mdiOpenInNew, mdiRefresh } from '@mdi/js'; import { Icon } from '@mdi/react'; import cx from 'classnames'; @@ -93,7 +94,7 @@ function GeneralSettings() { themes.data?.find(theme => `theme-${theme.ID}` === WebUI_Settings.theme) ), [themes, WebUI_Settings.theme]); - const handleExclusionChange = (event: any) => { + const handleExclusionChange = (event: ChangeEvent) => { const { checked, id } = event.target; if (checked) { diff --git a/src/pages/utilities/SeriesWithoutFilesUtility.tsx b/src/pages/utilities/SeriesWithoutFilesUtility.tsx index f494d72bf..fd0313cbd 100644 --- a/src/pages/utilities/SeriesWithoutFilesUtility.tsx +++ b/src/pages/utilities/SeriesWithoutFilesUtility.tsx @@ -103,7 +103,12 @@ function SeriesWithoutFilesUtility() { }; const renderOperations = (common = false) => { - const renderButton = (onClick: (...args: any) => void, icon: string, name: string, highlight = false) => ( + const renderButton = ( + onClick: React.MouseEventHandler, + icon: string, + name: string, + highlight = false, + ) => (