diff --git a/web/app.react.js b/web/app.react.js --- a/web/app.react.js +++ b/web/app.react.js @@ -287,7 +287,7 @@ getMainContentWithSwitcher(): React.Node { const { tab, settingsSection } = this.props.navInfo; - let mainContent; + let mainContent: React.Node; if (tab === 'settings') { if (settingsSection === 'account') { diff --git a/web/calendar/filter-panel.react.js b/web/calendar/filter-panel.react.js --- a/web/calendar/filter-panel.react.js +++ b/web/calendar/filter-panel.react.js @@ -85,7 +85,7 @@ this.inCurrentCommunity(item.threadInfo.id), ); - let filters = []; + let filters: React.Node[] = []; if (!this.state.query || filterThreadInfosInCurrentCommunity.length > 0) { filters.push( { if (!typeaheadMatchedStrings) { - return []; + return ([]: $ReadOnlyArray); } const suggestedUsers = getMentionTypeaheadUserSuggestions( userSearchIndex, @@ -655,7 +655,10 @@ props.inputState.typeaheadState.frozenChatMentionsCandidates, typeaheadMatchedStrings.query, ); - return [...suggestedUsers, ...suggestedChats]; + return ([ + ...suggestedUsers, + ...suggestedChats, + ]: $ReadOnlyArray); }, [ typeaheadMatchedStrings, userSearchIndex, diff --git a/web/chat/text-message.react.js b/web/chat/text-message.react.js --- a/web/chat/text-message.react.js +++ b/web/chat/text-message.react.js @@ -31,7 +31,7 @@ creator: { isViewer }, } = props.item.messageInfo; - const messageStyle = {}; + const messageStyle: { backgroundColor?: string } = {}; let darkColor = true; if (isViewer) { const threadColor = props.threadInfo.color; diff --git a/web/components/community-actions-menu.react.js b/web/components/community-actions-menu.react.js --- a/web/components/community-actions-menu.react.js +++ b/web/components/community-actions-menu.react.js @@ -12,6 +12,7 @@ import css from './community-actions-menu.css'; import MenuItem from '../components/menu-item.react.js'; +import type { MenuItemProps } from '../components/menu-item.react.js'; import Menu from '../components/menu.react.js'; import ManageInviteLinksModal from '../invite-links/manage-invite-links-modal.react.js'; import ViewInviteLinkModal from '../invite-links/view-invite-link-modal.react.js'; @@ -59,7 +60,7 @@ ); const items = React.useMemo(() => { - const itemSpecs = []; + const itemSpecs: MenuItemProps[] = []; if (canManageLinks) { itemSpecs.push({ diff --git a/web/components/menu-item.react.js b/web/components/menu-item.react.js --- a/web/components/menu-item.react.js +++ b/web/components/menu-item.react.js @@ -15,7 +15,7 @@ +text: string, +dangerous?: boolean, }; -type MenuItemProps = +export type MenuItemProps = | { ...MenuItemPropsBase, +icon: Icon, diff --git a/web/input/input-state-container.react.js b/web/input/input-state-container.react.js --- a/web/input/input-state-container.react.js +++ b/web/input/input-state-container.react.js @@ -147,13 +147,14 @@ +unregisterSendCallback: (() => mixed) => void, +textMessageCreationSideEffectsFunc: CreationSideEffectsFunc, }; -type State = { - +pendingUploads: { +type WritableState = { + pendingUploads: { [threadID: string]: { [localUploadID: string]: PendingMultimediaUpload }, }, - +textCursorPositions: { [threadID: string]: number }, - +typeaheadState: TypeaheadState, + textCursorPositions: { [threadID: string]: number }, + typeaheadState: TypeaheadState, }; +type State = $ReadOnly; type PropsAndState = { ...Props, @@ -193,7 +194,7 @@ state: { +[threadID: string]: T }, props: Props, ): ?{ [threadID: string]: T } { - const newState = {}; + const newState: { [string]: T } = {}; let updated = false; for (const threadID in state) { const newThreadID = @@ -220,7 +221,7 @@ return null; } - const stateUpdate = {}; + const stateUpdate: Partial = {}; if (pendingUploads) { stateUpdate.pendingUploads = pendingUploads; } @@ -518,7 +519,7 @@ this.setState(prevState => { const newThreadID = this.getRealizedOrPendingThreadID(threadID); const prevUploads = prevState.pendingUploads[newThreadID]; - const newUploads = {}; + const newUploads: { [string]: PendingMultimediaUpload } = {}; for (const localUploadID in prevUploads) { const upload = prevUploads[localUploadID]; if (upload.messageID !== localID) { @@ -588,8 +589,11 @@ draft: ?string, textCursorPosition: ?number, ) => { - let threadPendingUploads = []; - const assignedUploads = {}; + let threadPendingUploads: $ReadOnlyArray = + []; + const assignedUploads: { + [string]: $ReadOnlyArray, + } = {}; if (pendingUploads) { const [uploadsWithMessageIDs, uploadsWithoutMessageIDs] = _partition('messageID')(pendingUploads); @@ -740,7 +744,7 @@ | MediaMissionFailure | { success: true, pendingUpload: PendingMultimediaUpload }, }> { - const steps = [ + const steps: MediaMissionStep[] = [ { step: 'web_selection', filename: file.name, @@ -1164,7 +1168,7 @@ cancelPendingUpload(threadID: ?string, localUploadID: string) { invariant(threadID, 'threadID should be set in cancelPendingUpload'); - let revokeURL, abortRequest; + let revokeURL: ?string, abortRequest: ?() => void; this.setState( prevState => { const newThreadID = this.getRealizedOrPendingThreadID(threadID); @@ -1375,7 +1379,7 @@ if (!currentPendingUploads) { return {}; } - const newPendingUploads = {}; + const newPendingUploads: { [string]: PendingMultimediaUpload } = {}; let uploadAssigned = false; for (const localUploadID in currentPendingUploads) { const upload = currentPendingUploads[localUploadID]; @@ -1543,7 +1547,7 @@ if (!prevPendingUploads) { return {}; } - const newPendingUploads = {}; + const newPendingUploads: { [string]: PendingMultimediaUpload } = {}; let pendingUploadChanged = false; for (const localID in prevPendingUploads) { const pendingUpload = prevPendingUploads[localID]; diff --git a/web/loading-indicator.react.js b/web/loading-indicator.react.js --- a/web/loading-indicator.react.js +++ b/web/loading-indicator.react.js @@ -24,7 +24,7 @@ const size = props.size ? props.size : 'small'; const color = props.color ? props.color : 'white'; if (props.status === 'loading') { - const classNameInput = { + const classNameInput: { [string]: boolean } = { [css['loading-indicator-loading']]: true, [css['loading-indicator-loading-medium']]: hasRendered && size === 'medium', @@ -38,7 +38,7 @@ } return ; } else if (props.status === 'error') { - const classNameInput = { + const classNameInput: { [string]: boolean } = { [css['loading-indicator-error']]: true, [css['loading-indicator-error-black']]: tinycolor.equals(color, 'black'), }; diff --git a/web/media/blob-utils.js b/web/media/blob-utils.js --- a/web/media/blob-utils.js +++ b/web/media/blob-utils.js @@ -38,7 +38,7 @@ steps: $ReadOnlyArray, result: MediaMissionFailure | ProbeFileSuccess, }> { - const steps = []; + const steps: MediaMissionStep[] = []; let arrayBuffer, arrayBufferExceptionMessage; const arrayBufferStart = Date.now(); diff --git a/web/media/image-utils.js b/web/media/image-utils.js --- a/web/media/image-utils.js +++ b/web/media/image-utils.js @@ -61,7 +61,7 @@ +steps: $ReadOnlyArray, +result: GenerateThumbhashResult | MediaMissionFailure, }> { - const steps = []; + const steps: MediaMissionStep[] = []; const initialURI = URL.createObjectURL(file); const { steps: preloadSteps, result: image } = await preloadImage(initialURI); steps.push(...preloadSteps); diff --git a/web/media/media-utils.js b/web/media/media-utils.js --- a/web/media/media-utils.js +++ b/web/media/media-utils.js @@ -123,7 +123,7 @@ ]); const { steps: preloadSteps, result: image } = preloadResponse; - const steps = [...preloadSteps, orientationStep]; + const steps: MediaMissionStep[] = [...preloadSteps, orientationStep]; if (!image) { return { diff --git a/web/modals/chat/message-results-modal.react.js b/web/modals/chat/message-results-modal.react.js --- a/web/modals/chat/message-results-modal.react.js +++ b/web/modals/chat/message-results-modal.react.js @@ -7,7 +7,10 @@ useFetchPinnedMessages, } from 'lib/actions/message-actions.js'; import { useModalContext } from 'lib/components/modal-provider.react.js'; -import { messageListData } from 'lib/selectors/chat-selectors.js'; +import { + messageListData, + type ChatMessageInfoItem, +} from 'lib/selectors/chat-selectors.js'; import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors.js'; import { createMessageInfo, @@ -73,7 +76,7 @@ const sortedUniqueChatMessageInfoItems = React.useMemo(() => { if (!chatMessageInfos) { - return []; + return ([]: ChatMessageInfoItem[]); } const chatMessageInfoItems = chatMessageInfos.filter( diff --git a/web/modals/threads/settings/thread-settings-modal.react.js b/web/modals/threads/settings/thread-settings-modal.react.js --- a/web/modals/threads/settings/thread-settings-modal.react.js +++ b/web/modals/threads/settings/thread-settings-modal.react.js @@ -16,6 +16,7 @@ getSingleOtherUser, threadUIName, } from 'lib/shared/thread-utils.js'; +import type { RelationshipButton } from 'lib/types/relationship-types.js'; import { threadPermissions } from 'lib/types/thread-permission-types.js'; import { threadTypes } from 'lib/types/thread-types-enum.js'; import { type ThreadInfo, type ThreadChanges } from 'lib/types/thread-types.js'; @@ -88,7 +89,7 @@ const availableRelationshipActions = React.useMemo(() => { if (!otherUserInfo) { - return []; + return ([]: RelationshipButton[]); } return getAvailableRelationshipButtons(otherUserInfo); }, [otherUserInfo]); diff --git a/web/olm/olm-utils.js b/web/olm/olm-utils.js --- a/web/olm/olm-utils.js +++ b/web/olm/olm-utils.js @@ -14,7 +14,7 @@ return await olm.init({ locateFile }); } -let olmUtilityInstance; +let olmUtilityInstance: ?olm.Utility | Promise; function olmUtility(): Promise { if (!olmUtilityInstance) { olmUtilityInstance = (async () => { diff --git a/web/redux/action-types.js b/web/redux/action-types.js --- a/web/redux/action-types.js +++ b/web/redux/action-types.js @@ -25,7 +25,7 @@ allKeyserverIDs: $ReadOnlyArray, ): ((input: URLInfo) => Promise) => async urlInfo => { - const requests = {}; + const requests: { [string]: URLInfo } = {}; const { thread, inviteSecret, ...rest } = urlInfo; const threadKeyserverID = thread ? extractKeyserverIDFromID(thread) : null; diff --git a/web/redux/persist.js b/web/redux/persist.js --- a/web/redux/persist.js +++ b/web/redux/persist.js @@ -273,7 +273,7 @@ }; const keyserverStoreTransform: Transform = createTransform( (state: KeyserverStore): PersistedKeyserverStore => { - const keyserverInfos = {}; + const keyserverInfos: { [string]: PersistedKeyserverInfo } = {}; for (const key in state.keyserverInfos) { const { connection, updatesCurrentAsOf, sessionID, ...rest } = state.keyserverInfos[key]; @@ -285,7 +285,7 @@ }; }, (state: PersistedKeyserverStore): KeyserverStore => { - const keyserverInfos = {}; + const keyserverInfos: { [string]: KeyserverInfo } = {}; for (const key in state.keyserverInfos) { keyserverInfos[key] = { ...state.keyserverInfos[key], diff --git a/web/settings/relationship/add-users-list.react.js b/web/settings/relationship/add-users-list.react.js --- a/web/settings/relationship/add-users-list.react.js +++ b/web/settings/relationship/add-users-list.react.js @@ -14,7 +14,10 @@ UserRelationshipStatus, RelationshipAction, } from 'lib/types/relationship-types.js'; -import type { GlobalAccountUserInfo } from 'lib/types/user-types.js'; +import type { + GlobalAccountUserInfo, + AccountUserInfo, +} from 'lib/types/user-types.js'; import { useDispatchActionPromise, useServerCall, @@ -80,7 +83,8 @@ const searchTextPresent = searchText.length > 0; const userInfos = useSelector(state => state.userStore.userInfos); const mergedUserInfos = React.useMemo(() => { - const mergedInfos = {}; + const mergedInfos: { [string]: GlobalAccountUserInfo | AccountUserInfo } = + {}; for (const userInfo of serverSearchResults) { mergedInfos[userInfo.id] = userInfo; diff --git a/web/settings/tunnelbroker-message-list.react.js b/web/settings/tunnelbroker-message-list.react.js --- a/web/settings/tunnelbroker-message-list.react.js +++ b/web/settings/tunnelbroker-message-list.react.js @@ -27,7 +27,7 @@ return () => removeListener(listener); }, [addListener, listener, removeListener]); - let messageList = ( + let messageList: React.Node = (
No messages
diff --git a/web/url-utils.js b/web/url-utils.js --- a/web/url-utils.js +++ b/web/url-utils.js @@ -90,7 +90,7 @@ const { navInfo } = backupInfo; const now = backupInfo.now ? backupInfo.now : new Date(); - let year = urlInfo.year; + let year: ?number = urlInfo.year; if (!year && navInfo) { year = yearExtractor(navInfo.startDate, navInfo.endDate); } @@ -98,7 +98,7 @@ year = now.getFullYear(); } - let month = urlInfo.month; + let month: ?number = urlInfo.month; if (!month && navInfo) { month = monthExtractor(navInfo.startDate, navInfo.endDate); }