diff --git a/.github/actions/javascript/bumpVersion/bumpVersion.ts b/.github/actions/javascript/bumpVersion/bumpVersion.ts index f9215f36a844..85955ea81ff4 100644 --- a/.github/actions/javascript/bumpVersion/bumpVersion.ts +++ b/.github/actions/javascript/bumpVersion/bumpVersion.ts @@ -1,6 +1,7 @@ import * as core from '@actions/core'; import {exec as originalExec} from 'child_process'; import fs from 'fs'; +import type {PackageJson} from 'type-fest'; import {promisify} from 'util'; import {generateAndroidVersionCode, updateAndroidVersion, updateiOSVersion} from '@github/libs/nativeVersionUpdater'; import * as versionUpdater from '@github/libs/versionUpdater'; @@ -47,8 +48,12 @@ if (!semanticVersionLevel || !Object.keys(versionUpdater.SEMANTIC_VERSION_LEVELS console.log(`Invalid input for 'SEMVER_LEVEL': ${semanticVersionLevel}`, `Defaulting to: ${semanticVersionLevel}`); } -const {version: previousVersion}: {version: string} = JSON.parse(fs.readFileSync('./package.json').toString()); -const newVersion = versionUpdater.incrementVersion(previousVersion, semanticVersionLevel); +const {version: previousVersion}: PackageJson = JSON.parse(fs.readFileSync('./package.json').toString()); +if (!previousVersion) { + core.setFailed('Error: Could not read package.json'); +} + +const newVersion = versionUpdater.incrementVersion(previousVersion ?? '', semanticVersionLevel); console.log(`Previous version: ${previousVersion}`, `New version: ${newVersion}`); updateNativeVersions(newVersion); diff --git a/src/components/AttachmentPicker/index.native.tsx b/src/components/AttachmentPicker/index.native.tsx index ad4cf023c096..822a5650e758 100644 --- a/src/components/AttachmentPicker/index.native.tsx +++ b/src/components/AttachmentPicker/index.native.tsx @@ -248,7 +248,13 @@ function AttachmentPicker({type = CONST.ATTACHMENT_PICKER_TYPE.FILE, children, s completeAttachmentSelection.current(result); }) .catch((error) => { - showGeneralAlert(error.message); + let errorMessage; + if (error instanceof Error) { + errorMessage = error.message; + } else { + errorMessage = String(error.message); + } + showGeneralAlert(errorMessage); throw error; }); }, diff --git a/src/components/Attachments/AttachmentCarousel/index.tsx b/src/components/Attachments/AttachmentCarousel/index.tsx index 3b873d437e95..42536ae208ae 100644 --- a/src/components/Attachments/AttachmentCarousel/index.tsx +++ b/src/components/Attachments/AttachmentCarousel/index.tsx @@ -92,13 +92,14 @@ function AttachmentCarousel({report, reportActions, parentReportActions, source, return; } + const item: Attachment = entry.item; if (entry.index !== null) { setPage(entry.index); - setActiveSource(entry.item.source); + setActiveSource(item.source); } if (onNavigate) { - onNavigate(entry.item as Attachment); + onNavigate(item); } }, [isFullScreenRef, onNavigate], diff --git a/src/components/Onfido/BaseOnfidoWeb.tsx b/src/components/Onfido/BaseOnfidoWeb.tsx index fefe2ab0a6d1..af9b99efda33 100644 --- a/src/components/Onfido/BaseOnfidoWeb.tsx +++ b/src/components/Onfido/BaseOnfidoWeb.tsx @@ -93,8 +93,13 @@ function initializeOnfido({sdkToken, onSuccess, onError, onUserExit, preferredLo onSuccess(data); }, onError: (error) => { + let errorMessage; + if (error instanceof Error) { + errorMessage = error.message; + } else { + errorMessage = CONST.ERROR.UNKNOWN_ERROR; + } const errorType = error.type; - const errorMessage = error.message ?? CONST.ERROR.UNKNOWN_ERROR; Log.hmmm('Onfido error', {errorType, errorMessage}); if (errorType === CONST.WALLET.ERROR.ONFIDO_USER_CONSENT_DENIED) { onUserExit(); diff --git a/src/components/Onfido/index.native.tsx b/src/components/Onfido/index.native.tsx index a7e7a277fff9..f1f590b46786 100644 --- a/src/components/Onfido/index.native.tsx +++ b/src/components/Onfido/index.native.tsx @@ -30,14 +30,19 @@ function Onfido({sdkToken, onUserExit, onSuccess, onError}: OnfidoProps) { }) .then(onSuccess) .catch((error) => { - const errorMessage = error.message ?? CONST.ERROR.UNKNOWN_ERROR; + let errorMessage: string; + if (error instanceof Error) { + errorMessage = error.message; + } else { + errorMessage = CONST.ERROR.UNKNOWN_ERROR; + } const errorType = error.type; Log.hmmm('Onfido error on native', {errorType, errorMessage}); // If the user cancels the Onfido flow we won't log this error as it's normal. In the React Native SDK the user exiting the flow will trigger this error which we can use as // our "user exited the flow" callback. On web, this event has it's own callback passed as a config so we don't need to bother with this there. - if ([CONST.ONFIDO.ERROR.USER_CANCELLED, CONST.ONFIDO.ERROR.USER_TAPPED_BACK, CONST.ONFIDO.ERROR.USER_EXITED].includes(errorMessage)) { + if (([CONST.ONFIDO.ERROR.USER_CANCELLED, CONST.ONFIDO.ERROR.USER_TAPPED_BACK, CONST.ONFIDO.ERROR.USER_EXITED] as string[]).includes(errorMessage)) { onUserExit(); return; } diff --git a/src/components/SignInButtons/AppleSignIn/index.android.tsx b/src/components/SignInButtons/AppleSignIn/index.android.tsx index cfd1c48ee8b5..81d360d9f072 100644 --- a/src/components/SignInButtons/AppleSignIn/index.android.tsx +++ b/src/components/SignInButtons/AppleSignIn/index.android.tsx @@ -38,7 +38,7 @@ function AppleSignIn() { appleSignInRequest() .then((token) => Session.beginAppleSignIn(token)) .catch((e) => { - if (e.message === appleAuthAndroid.Error.SIGNIN_CANCELLED) { + if (e instanceof Error && e.message === appleAuthAndroid.Error.SIGNIN_CANCELLED) { return null; } Log.alert('[Apple Sign In] Apple authentication failed', e); diff --git a/src/libs/EmojiUtils.ts b/src/libs/EmojiUtils.ts index fc84bb7261f6..0be7e76a0aa9 100644 --- a/src/libs/EmojiUtils.ts +++ b/src/libs/EmojiUtils.ts @@ -10,6 +10,8 @@ import ONYXKEYS from '@src/ONYXKEYS'; import type {FrequentlyUsedEmoji, Locale} from '@src/types/onyx'; import type {ReportActionReaction, UsersReactions} from '@src/types/onyx/ReportActionReactions'; import type IconAsset from '@src/types/utils/IconAsset'; +import type EmojiTrie from './EmojiTrie'; +import type {SupportedLanguage} from './EmojiTrie'; type HeaderIndice = {code: string; index: number; icon: IconAsset}; type EmojiSpacer = {code: string; spacer: boolean}; @@ -312,9 +314,9 @@ function getAddedEmojis(currentEmojis: Emoji[], formerEmojis: Emoji[]): Emoji[] */ function replaceEmojis(text: string, preferredSkinTone: OnyxEntry = CONST.EMOJI_DEFAULT_SKIN_TONE, lang: Locale = CONST.LOCALES.DEFAULT): ReplacedEmoji { // emojisTrie is importing the emoji JSON file on the app starting and we want to avoid it - const emojisTrie = require('./EmojiTrie').default; + const emojisTrie: typeof EmojiTrie = require('./EmojiTrie').default; - const trie = emojisTrie[lang]; + const trie = emojisTrie[lang as SupportedLanguage]; if (!trie) { return {text, emojis: []}; } @@ -390,9 +392,9 @@ function replaceAndExtractEmojis(text: string, preferredSkinTone: OnyxEntry = TranslationFlatObject[TKey] extends */ const translationCache = new Map, Map>( Object.values(CONST.LOCALES).reduce((cache, locale) => { - cache.push([locale, new Map()]); + cache.push([locale, new Map()]); return cache; }, [] as Array<[ValueOf, Map]>), ); diff --git a/src/libs/Pusher/pusher.ts b/src/libs/Pusher/pusher.ts index 48c5e5c1409f..cdce408d8d43 100644 --- a/src/libs/Pusher/pusher.ts +++ b/src/libs/Pusher/pusher.ts @@ -198,7 +198,7 @@ function bindEventToChannel(channel: Channel // packet. if (chunkedEvent.receivedFinal && chunkedEvent.chunks.length === Object.keys(chunkedEvent.chunks).length) { try { - eventCallback(JSON.parse(chunkedEvent.chunks.join(''))); + eventCallback(JSON.parse(chunkedEvent.chunks.join('')) as EventData); } catch (err) { Log.alert('[Pusher] Unable to parse chunked JSON response from Pusher', { error: err, diff --git a/src/libs/actions/Device/index.ts b/src/libs/actions/Device/index.ts index e7c19d20e4fe..5309f67ea91a 100644 --- a/src/libs/actions/Device/index.ts +++ b/src/libs/actions/Device/index.ts @@ -43,7 +43,15 @@ function setDeviceID() { Log.info('Got new deviceID', false, uniqueID); Onyx.set(ONYXKEYS.DEVICE_ID, uniqueID); }) - .catch((err) => Log.info('Found existing deviceID', false, err.message)); + .catch((err) => { + let errorMessage; + if (err instanceof Error) { + errorMessage = err.message; + } else { + errorMessage = String(err.message); + } + Log.info('Found existing deviceID', false, errorMessage); + }); } /** diff --git a/tests/e2e/server/index.ts b/tests/e2e/server/index.ts index 51b73447bab4..0854c5d29db9 100644 --- a/tests/e2e/server/index.ts +++ b/tests/e2e/server/index.ts @@ -154,7 +154,13 @@ const createServerInstance = (): ServerInstance => { res.end('Error executing command'); }) .catch((error) => { - Logger.error('Error executing command', error); + let errorString; + if (error instanceof Error) { + errorString = error.toString(); + } else { + errorString = String(error); + } + Logger.error('Error executing command', errorString); res.statusCode = 500; res.end('Error executing command'); }); diff --git a/tests/ui/UnreadIndicatorsTest.tsx b/tests/ui/UnreadIndicatorsTest.tsx index e5c7e0359eed..5f8fa228d191 100644 --- a/tests/ui/UnreadIndicatorsTest.tsx +++ b/tests/ui/UnreadIndicatorsTest.tsx @@ -77,7 +77,7 @@ const createAddListenerMock = (): ListenerMock => { transitionEndListeners.forEach((transitionEndListener) => transitionEndListener()); }; - const addListener: jest.Mock = jest.fn().mockImplementation((listener, callback) => { + const addListener: jest.Mock = jest.fn().mockImplementation((listener, callback: () => void) => { if (listener === 'transitionEnd') { transitionEndListeners.push(callback); } diff --git a/tests/unit/MiddlewareTest.ts b/tests/unit/MiddlewareTest.ts index cc4bf7d0df6b..6954b22b2706 100644 --- a/tests/unit/MiddlewareTest.ts +++ b/tests/unit/MiddlewareTest.ts @@ -49,9 +49,9 @@ describe('Middleware', () => { expect(global.fetch).toHaveBeenCalledTimes(2); expect(global.fetch).toHaveBeenLastCalledWith('https://www.expensify.com.dev/api/AddComment?', expect.anything()); - TestHelper.assertFormDataMatchesObject((global.fetch as jest.Mock).mock.calls[1][1].body, {reportID: '1234', reportActionID: '5678'}); + TestHelper.assertFormDataMatchesObject((global.fetch as jest.Mock).mock.calls[1][1].body as TestHelper.FormData, {reportID: '1234', reportActionID: '5678'}); expect(global.fetch).toHaveBeenNthCalledWith(1, 'https://www.expensify.com.dev/api/OpenReport?', expect.anything()); - TestHelper.assertFormDataMatchesObject((global.fetch as jest.Mock).mock.calls[0][1].body, {reportID: '1234'}); + TestHelper.assertFormDataMatchesObject((global.fetch as jest.Mock).mock.calls[0][1].body as TestHelper.FormData, {reportID: '1234'}); }); test('Request with preexistingReportID', async () => { @@ -93,9 +93,9 @@ describe('Middleware', () => { expect(global.fetch).toHaveBeenCalledTimes(2); expect(global.fetch).toHaveBeenLastCalledWith('https://www.expensify.com.dev/api/AddComment?', expect.anything()); - TestHelper.assertFormDataMatchesObject((global.fetch as jest.Mock).mock.calls[1][1].body, {reportID: '5555', reportActionID: '5678'}); + TestHelper.assertFormDataMatchesObject((global.fetch as jest.Mock).mock.calls[1][1].body as TestHelper.FormData, {reportID: '5555', reportActionID: '5678'}); expect(global.fetch).toHaveBeenNthCalledWith(1, 'https://www.expensify.com.dev/api/OpenReport?', expect.anything()); - TestHelper.assertFormDataMatchesObject((global.fetch as jest.Mock).mock.calls[0][1].body, {reportID: '1234'}); + TestHelper.assertFormDataMatchesObject((global.fetch as jest.Mock).mock.calls[0][1].body as TestHelper.FormData, {reportID: '1234'}); }); }); }); diff --git a/tests/unit/markPullRequestsAsDeployedTest.ts b/tests/unit/markPullRequestsAsDeployedTest.ts index d533435273d4..24a6733d1244 100644 --- a/tests/unit/markPullRequestsAsDeployedTest.ts +++ b/tests/unit/markPullRequestsAsDeployedTest.ts @@ -196,7 +196,7 @@ platform | result }); it('comments on pull requests correctly for a standard production deploy', async () => { - mockGetInput.mockImplementation((key) => { + mockGetInput.mockImplementation((key: string) => { if (key === 'IS_PRODUCTION_DEPLOY') { return true; } @@ -226,7 +226,7 @@ platform | result }); it('comments on pull requests correctly for a cherry pick', async () => { - mockGetInput.mockImplementation((key) => { + mockGetInput.mockImplementation((key: string) => { if (key === 'PR_LIST') { return JSON.stringify([3]); } @@ -281,7 +281,7 @@ platform | result }); it('comments on pull requests correctly when one platform fails', async () => { - mockGetInput.mockImplementation((key) => { + mockGetInput.mockImplementation((key: string) => { if (key === 'ANDROID') { return 'skipped'; } diff --git a/tests/utils/TestHelper.ts b/tests/utils/TestHelper.ts index bd107ba6ed56..11befebea340 100644 --- a/tests/utils/TestHelper.ts +++ b/tests/utils/TestHelper.ts @@ -230,7 +230,7 @@ const createAddListenerMock = () => { transitionEndListeners.forEach((transitionEndListener) => transitionEndListener()); }; - const addListener = jest.fn().mockImplementation((listener, callback) => { + const addListener = jest.fn().mockImplementation((listener, callback: Listener) => { if (listener === 'transitionEnd') { transitionEndListeners.push(callback); } @@ -242,5 +242,5 @@ const createAddListenerMock = () => { return {triggerTransitionEnd, addListener}; }; -export type {MockFetch}; +export type {MockFetch, FormData}; export {assertFormDataMatchesObject, buildPersonalDetails, buildTestReportComment, createAddListenerMock, getGlobalFetchMock, setPersonalDetails, signInWithTestUser, signOutTestUser}; diff --git a/workflow_tests/utils/ExtendedAct.ts b/workflow_tests/utils/ExtendedAct.ts index b0f4d7e159e4..e2bb12ec8e01 100644 --- a/workflow_tests/utils/ExtendedAct.ts +++ b/workflow_tests/utils/ExtendedAct.ts @@ -42,14 +42,14 @@ class ExtendedAct extends Act { if (opts.workflowFile) { workflowFiles = [path.basename(opts.workflowFile)]; } else if (this['workflowFile'] !== this['cwd']) { - workflowFiles = [path.basename(this['workflowFile'])]; + workflowFiles = [path.basename(this['workflowFile'] as string)]; } else { const availableWorkflows = await this.list(undefined, opts.cwd, opts.workflowFile); workflowFiles = availableWorkflows.filter(filter).map((workflow: Workflow) => workflow.workflowFile); } return workflowFiles.map((workflowFile) => { - const jobMocker = new JobMocker(workflowFile, opts.cwd ?? this['cwd']); + const jobMocker = new JobMocker(workflowFile, opts.cwd ?? (this['cwd'] as string)); return jobMocker.mock(opts.mockJobs); }); } diff --git a/workflow_tests/utils/preGenerateTest.ts b/workflow_tests/utils/preGenerateTest.ts index 25bdb8f00ae3..b1fd99b72794 100644 --- a/workflow_tests/utils/preGenerateTest.ts +++ b/workflow_tests/utils/preGenerateTest.ts @@ -275,7 +275,7 @@ checkIfMocksFileExists(workflowTestMocksDirectory, workflowTestMocksFileName); const workflowTestAssertionsFileName = `${workflowName}Assertions.ts`; checkIfAssertionsFileExists(workflowTestAssertionsDirectory, workflowTestAssertionsFileName); -const workflow = yaml.parse(fs.readFileSync(workflowFilePath, 'utf8')); +const workflow: YamlWorkflow = yaml.parse(fs.readFileSync(workflowFilePath, 'utf8')); const workflowJobs = parseWorkflowFile(workflow); const mockFileContent = getMockFileContent(workflowName, workflowJobs);