From e6868d833db0809bd782a3bfd1e1716e1b6b5501 Mon Sep 17 00:00:00 2001 From: Greg Price Date: Thu, 10 Jan 2019 21:34:31 -0800 Subject: [PATCH] actions: Clarify to Flow that these constants are type-tags. When Flow sees a definition like `const FOO = 'FOO'`, it knows for some purposes that `FOO` is specifically `'FOO'`... but for others, it apparently broadens it to `string`. This is facebook/flow#2639. One consequence is that when we say switch (action.type) { case NOT_FOO_LOL: // ... use `action` ... break; // ... } with a `case` statement for a value of `type` that we've claimed is *impossible*... Flow quietly just decides that `action` has type `empty` and there's nothing to worry about. Then if our code goes and passes that `action` value to *any function at all*, Flow considers it valid. After all, there are no values of type `empty` (that's what `empty` is all about)... so it's true that every value of type `empty` is a valid value of whatever type it is that the function expected. So, that's pretty unfortunate. Fortunately, there is a workaround that causes Flow to behave better here: duplicate the value into the type, like `const FOO: 'FOO' = 'FOO'`. (This trick due to @geraldyeo and @fagerbua, in comments on facebook/flow#2377 -- thanks!) Do that, then. --- Made the edit with perl -i -0pe \ 's/export const ([A-Z_]+)\K =/: "$1" =/g' \ src/actionConstants.js and then manual fixup on the one exceptional case `REHYDRATE`, which Flow kindly pointed out. We had a whole bunch of type errors of the kind this hides; the bulk of them were for Event*Action types, and their fixes went into the parent commit. This commit adds one more missing action type which a number of reducers had type errors on, and a few other simple fixes. PS: A quick tip for reading this diff: `git log -p --patience`. --- src/actionConstants.js | 174 +++++++++--------- src/actionTypes.js | 2 +- src/boot/__tests__/reducers-test.js | 1 + .../__tests__/caughtUpReducers-test.js | 1 + src/loading/__tests__/loadingReducer-test.js | 1 + 5 files changed, 94 insertions(+), 85 deletions(-) diff --git a/src/actionConstants.js b/src/actionConstants.js index 7ac2e2cffb6..c9f1ec7cdd7 100644 --- a/src/actionConstants.js +++ b/src/actionConstants.js @@ -1,92 +1,98 @@ /* @flow strict */ -export const REHYDRATE = 'persist/REHYDRATE'; - -export const APP_ONLINE = 'APP_ONLINE'; -export const APP_ORIENTATION = 'APP_ORIENTATION'; -export const APP_STATE = 'APP_STATE'; -export const DEAD_QUEUE = 'DEAD_QUEUE'; - -export const REALM_ADD = 'REALM_ADD'; -export const ACCOUNT_ADD_SUCCEEDED = 'ACCOUNT_ADD_SUCCEEDED'; -export const ACCOUNT_REMOVE = 'ACCOUNT_REMOVE'; -export const ACCOUNT_SWITCH = 'ACCOUNT_SWITCH'; - -export const LOGIN_SUCCESS = 'LOGIN_SUCCESS'; -export const HTTP_UNAUTHORIZED = 'HTTP_UNAUTHORIZED'; -export const LOGOUT = 'LOGOUT'; - -export const REALM_INIT = 'REALM_INIT'; -export const DO_NARROW = 'DO_NARROW'; - -export const INIT_SAFE_AREA_INSETS = 'INIT_SAFE_AREA_INSETS'; -export const INITIAL_FETCH_START = 'INITIAL_FETCH_START'; -export const INITIAL_FETCH_COMPLETE = 'INITIAL_FETCH_COMPLETE'; -export const INIT_STREAMS = 'INIT_STREAMS'; -export const INIT_SUBSCRIPTIONS = 'INIT_SUBSCRIPTIONS'; -export const INIT_REALM_EMOJI = 'INIT_REALM_EMOJI'; -export const INIT_REALM_FILTER = 'INIT_REALM_FILTER'; -export const INIT_TOPICS = 'INIT_TOPICS'; - -export const EVENT_NEW_MESSAGE = 'EVENT_NEW_MESSAGE'; -export const EVENT_MESSAGE_DELETE = 'EVENT_MESSAGE_DELETE'; -export const EVENT_STREAM_ADD = 'EVENT_STREAM_ADD'; -export const EVENT_STREAM_REMOVE = 'EVENT_STREAM_REMOVE'; -export const EVENT_STREAM_UPDATE = 'EVENT_STREAM_UPDATE'; -export const EVENT_STREAM_OCCUPY = 'EVENT_STREAM_OCCUPY'; -export const EVENT_SUBSCRIPTION_ADD = 'EVENT_SUBSCRIPTION_ADD'; -export const EVENT_SUBSCRIPTION_REMOVE = 'EVENT_SUBSCRIPTION_REMOVE'; -export const EVENT_SUBSCRIPTION_UPDATE = 'EVENT_SUBSCRIPTION_UPDATE'; -export const EVENT_SUBSCRIPTION_PEER_ADD = 'EVENT_SUBSCRIPTION_PEER_ADD'; -export const EVENT_SUBSCRIPTION_PEER_REMOVE = 'EVENT_SUBSCRIPTION_PEER_REMOVE'; -export const EVENT_UPDATE_MESSAGE = 'EVENT_UPDATE_MESSAGE'; -export const EVENT_REACTION_ADD = 'EVENT_REACTION_ADD'; -export const EVENT_REACTION_REMOVE = 'EVENT_REACTION_REMOVE'; -export const EVENT_PRESENCE = 'EVENT_PRESENCE'; -export const EVENT_TYPING_START = 'EVENT_TYPING_START'; -export const EVENT_TYPING_STOP = 'EVENT_TYPING_STOP'; -export const EVENT_UPDATE_MESSAGE_FLAGS = 'EVENT_UPDATE_MESSAGE_FLAGS'; -export const EVENT_USER_ADD = 'EVENT_USER_ADD'; -export const EVENT_USER_REMOVE = 'EVENT_USER_REMOVE'; -export const EVENT_USER_UPDATE = 'EVENT_USER_UPDATE'; -export const EVENT_MUTED_TOPICS = 'EVENT_MUTED_TOPICS'; - -export const EVENT_USER_GROUP_ADD = 'EVENT_USER_GROUP_ADD'; -export const EVENT_USER_GROUP_REMOVE = 'EVENT_USER_GROUP_REMOVE'; -export const EVENT_USER_GROUP_UPDATE = 'EVENT_USER_GROUP_UPDATE'; -export const EVENT_USER_GROUP_ADD_MEMBERS = 'EVENT_USER_GROUP_ADD_MEMBERS'; -export const EVENT_USER_GROUP_REMOVE_MEMBERS = 'EVENT_USER_GROUP_REMOVE_MEMBERS'; - -export const MESSAGE_FETCH_START = 'MESSAGE_FETCH_START'; -export const MESSAGE_FETCH_COMPLETE = 'MESSAGE_FETCH_COMPLETE'; - -export const PRESENCE_RESPONSE = 'PRESENCE_RESPONSE'; -export const GET_USER_RESPONSE = 'GET_USER_RESPONSE'; -export const MARK_MESSAGES_READ = 'MARK_MESSAGES_READ'; -export const SETTINGS_CHANGE = 'SETTINGS_CHANGE'; -export const DEBUG_FLAG_TOGGLE = 'DEBUG_FLAG_TOGGLE'; - -export const GOT_PUSH_TOKEN = 'GOT_PUSH_TOKEN'; -export const ACK_PUSH_TOKEN = 'ACK_PUSH_TOKEN'; -export const UNACK_PUSH_TOKEN = 'UNACK_PUSH_TOKEN'; - -export const EVENT_REALM_EMOJI_UPDATE = 'EVENT_REALM_EMOJI_UPDATE'; -export const EVENT_REALM_FILTERS = 'EVENT_REALM_FILTERS'; - -export const EVENT_UPDATE_DISPLAY_SETTINGS = 'EVENT_UPDATE_DISPLAY_SETTINGS'; -export const EVENT_UPDATE_GLOBAL_NOTIFICATIONS_SETTINGS = +export const REHYDRATE: 'persist/REHYDRATE' = 'persist/REHYDRATE'; + +export const APP_ONLINE: 'APP_ONLINE' = 'APP_ONLINE'; +export const APP_ORIENTATION: 'APP_ORIENTATION' = 'APP_ORIENTATION'; +export const APP_STATE: 'APP_STATE' = 'APP_STATE'; +export const DEAD_QUEUE: 'DEAD_QUEUE' = 'DEAD_QUEUE'; + +export const REALM_ADD: 'REALM_ADD' = 'REALM_ADD'; +export const ACCOUNT_ADD_SUCCEEDED: 'ACCOUNT_ADD_SUCCEEDED' = 'ACCOUNT_ADD_SUCCEEDED'; +export const ACCOUNT_REMOVE: 'ACCOUNT_REMOVE' = 'ACCOUNT_REMOVE'; +export const ACCOUNT_SWITCH: 'ACCOUNT_SWITCH' = 'ACCOUNT_SWITCH'; + +export const LOGIN_SUCCESS: 'LOGIN_SUCCESS' = 'LOGIN_SUCCESS'; +export const HTTP_UNAUTHORIZED: 'HTTP_UNAUTHORIZED' = 'HTTP_UNAUTHORIZED'; +export const LOGOUT: 'LOGOUT' = 'LOGOUT'; + +export const REALM_INIT: 'REALM_INIT' = 'REALM_INIT'; +export const DO_NARROW: 'DO_NARROW' = 'DO_NARROW'; + +export const INIT_SAFE_AREA_INSETS: 'INIT_SAFE_AREA_INSETS' = 'INIT_SAFE_AREA_INSETS'; +export const INITIAL_FETCH_START: 'INITIAL_FETCH_START' = 'INITIAL_FETCH_START'; +export const INITIAL_FETCH_COMPLETE: 'INITIAL_FETCH_COMPLETE' = 'INITIAL_FETCH_COMPLETE'; +export const INIT_STREAMS: 'INIT_STREAMS' = 'INIT_STREAMS'; +export const INIT_SUBSCRIPTIONS: 'INIT_SUBSCRIPTIONS' = 'INIT_SUBSCRIPTIONS'; +export const INIT_REALM_EMOJI: 'INIT_REALM_EMOJI' = 'INIT_REALM_EMOJI'; +export const INIT_REALM_FILTER: 'INIT_REALM_FILTER' = 'INIT_REALM_FILTER'; +export const INIT_TOPICS: 'INIT_TOPICS' = 'INIT_TOPICS'; + +export const EVENT_NEW_MESSAGE: 'EVENT_NEW_MESSAGE' = 'EVENT_NEW_MESSAGE'; +export const EVENT_MESSAGE_DELETE: 'EVENT_MESSAGE_DELETE' = 'EVENT_MESSAGE_DELETE'; +export const EVENT_STREAM_ADD: 'EVENT_STREAM_ADD' = 'EVENT_STREAM_ADD'; +export const EVENT_STREAM_REMOVE: 'EVENT_STREAM_REMOVE' = 'EVENT_STREAM_REMOVE'; +export const EVENT_STREAM_UPDATE: 'EVENT_STREAM_UPDATE' = 'EVENT_STREAM_UPDATE'; +export const EVENT_STREAM_OCCUPY: 'EVENT_STREAM_OCCUPY' = 'EVENT_STREAM_OCCUPY'; +export const EVENT_SUBSCRIPTION_ADD: 'EVENT_SUBSCRIPTION_ADD' = 'EVENT_SUBSCRIPTION_ADD'; +export const EVENT_SUBSCRIPTION_REMOVE: 'EVENT_SUBSCRIPTION_REMOVE' = 'EVENT_SUBSCRIPTION_REMOVE'; +export const EVENT_SUBSCRIPTION_UPDATE: 'EVENT_SUBSCRIPTION_UPDATE' = 'EVENT_SUBSCRIPTION_UPDATE'; +export const EVENT_SUBSCRIPTION_PEER_ADD: 'EVENT_SUBSCRIPTION_PEER_ADD' = + 'EVENT_SUBSCRIPTION_PEER_ADD'; +export const EVENT_SUBSCRIPTION_PEER_REMOVE: 'EVENT_SUBSCRIPTION_PEER_REMOVE' = + 'EVENT_SUBSCRIPTION_PEER_REMOVE'; +export const EVENT_UPDATE_MESSAGE: 'EVENT_UPDATE_MESSAGE' = 'EVENT_UPDATE_MESSAGE'; +export const EVENT_REACTION_ADD: 'EVENT_REACTION_ADD' = 'EVENT_REACTION_ADD'; +export const EVENT_REACTION_REMOVE: 'EVENT_REACTION_REMOVE' = 'EVENT_REACTION_REMOVE'; +export const EVENT_PRESENCE: 'EVENT_PRESENCE' = 'EVENT_PRESENCE'; +export const EVENT_TYPING_START: 'EVENT_TYPING_START' = 'EVENT_TYPING_START'; +export const EVENT_TYPING_STOP: 'EVENT_TYPING_STOP' = 'EVENT_TYPING_STOP'; +export const EVENT_UPDATE_MESSAGE_FLAGS: 'EVENT_UPDATE_MESSAGE_FLAGS' = + 'EVENT_UPDATE_MESSAGE_FLAGS'; +export const EVENT_USER_ADD: 'EVENT_USER_ADD' = 'EVENT_USER_ADD'; +export const EVENT_USER_REMOVE: 'EVENT_USER_REMOVE' = 'EVENT_USER_REMOVE'; +export const EVENT_USER_UPDATE: 'EVENT_USER_UPDATE' = 'EVENT_USER_UPDATE'; +export const EVENT_MUTED_TOPICS: 'EVENT_MUTED_TOPICS' = 'EVENT_MUTED_TOPICS'; + +export const EVENT_USER_GROUP_ADD: 'EVENT_USER_GROUP_ADD' = 'EVENT_USER_GROUP_ADD'; +export const EVENT_USER_GROUP_REMOVE: 'EVENT_USER_GROUP_REMOVE' = 'EVENT_USER_GROUP_REMOVE'; +export const EVENT_USER_GROUP_UPDATE: 'EVENT_USER_GROUP_UPDATE' = 'EVENT_USER_GROUP_UPDATE'; +export const EVENT_USER_GROUP_ADD_MEMBERS: 'EVENT_USER_GROUP_ADD_MEMBERS' = + 'EVENT_USER_GROUP_ADD_MEMBERS'; +export const EVENT_USER_GROUP_REMOVE_MEMBERS: 'EVENT_USER_GROUP_REMOVE_MEMBERS' = + 'EVENT_USER_GROUP_REMOVE_MEMBERS'; + +export const MESSAGE_FETCH_START: 'MESSAGE_FETCH_START' = 'MESSAGE_FETCH_START'; +export const MESSAGE_FETCH_COMPLETE: 'MESSAGE_FETCH_COMPLETE' = 'MESSAGE_FETCH_COMPLETE'; + +export const PRESENCE_RESPONSE: 'PRESENCE_RESPONSE' = 'PRESENCE_RESPONSE'; +export const GET_USER_RESPONSE: 'GET_USER_RESPONSE' = 'GET_USER_RESPONSE'; +export const MARK_MESSAGES_READ: 'MARK_MESSAGES_READ' = 'MARK_MESSAGES_READ'; +export const SETTINGS_CHANGE: 'SETTINGS_CHANGE' = 'SETTINGS_CHANGE'; +export const DEBUG_FLAG_TOGGLE: 'DEBUG_FLAG_TOGGLE' = 'DEBUG_FLAG_TOGGLE'; + +export const GOT_PUSH_TOKEN: 'GOT_PUSH_TOKEN' = 'GOT_PUSH_TOKEN'; +export const ACK_PUSH_TOKEN: 'ACK_PUSH_TOKEN' = 'ACK_PUSH_TOKEN'; +export const UNACK_PUSH_TOKEN: 'UNACK_PUSH_TOKEN' = 'UNACK_PUSH_TOKEN'; + +export const EVENT_REALM_EMOJI_UPDATE: 'EVENT_REALM_EMOJI_UPDATE' = 'EVENT_REALM_EMOJI_UPDATE'; +export const EVENT_REALM_FILTERS: 'EVENT_REALM_FILTERS' = 'EVENT_REALM_FILTERS'; + +export const EVENT_UPDATE_DISPLAY_SETTINGS: 'EVENT_UPDATE_DISPLAY_SETTINGS' = + 'EVENT_UPDATE_DISPLAY_SETTINGS'; +export const EVENT_UPDATE_GLOBAL_NOTIFICATIONS_SETTINGS: 'EVENT_UPDATE_GLOBAL_NOTIFICATIONS_SETTINGS' = 'EVENT_UPDATE_GLOBAL_NOTIFICATIONS_SETTINGS'; -export const START_EDIT_MESSAGE = 'START_EDIT_MESSAGE'; -export const CANCEL_EDIT_MESSAGE = 'CANCEL_EDIT_MESSAGE'; +export const START_EDIT_MESSAGE: 'START_EDIT_MESSAGE' = 'START_EDIT_MESSAGE'; +export const CANCEL_EDIT_MESSAGE: 'CANCEL_EDIT_MESSAGE' = 'CANCEL_EDIT_MESSAGE'; -export const INIT_ALERT_WORDS = 'INIT_ALERT_WORDS'; +export const INIT_ALERT_WORDS: 'INIT_ALERT_WORDS' = 'INIT_ALERT_WORDS'; -export const MESSAGE_SEND_START = 'MESSAGE_SEND_START'; -export const MESSAGE_SEND_COMPLETE = 'MESSAGE_SEND_COMPLETE'; +export const MESSAGE_SEND_START: 'MESSAGE_SEND_START' = 'MESSAGE_SEND_START'; +export const MESSAGE_SEND_COMPLETE: 'MESSAGE_SEND_COMPLETE' = 'MESSAGE_SEND_COMPLETE'; -export const TOGGLE_OUTBOX_SENDING = 'TOGGLE_OUTBOX_SENDING'; -export const DELETE_OUTBOX_MESSAGE = 'DELETE_OUTBOX_MESSAGE'; +export const TOGGLE_OUTBOX_SENDING: 'TOGGLE_OUTBOX_SENDING' = 'TOGGLE_OUTBOX_SENDING'; +export const DELETE_OUTBOX_MESSAGE: 'DELETE_OUTBOX_MESSAGE' = 'DELETE_OUTBOX_MESSAGE'; -export const DRAFT_UPDATE = 'DRAFT_UPDATE'; +export const DRAFT_UPDATE: 'DRAFT_UPDATE' = 'DRAFT_UPDATE'; -export const CLEAR_TYPING = 'CLEAR_TYPING'; +export const CLEAR_TYPING: 'CLEAR_TYPING' = 'CLEAR_TYPING'; diff --git a/src/actionTypes.js b/src/actionTypes.js index ce19017e999..50a0431c8fc 100644 --- a/src/actionTypes.js +++ b/src/actionTypes.js @@ -643,7 +643,7 @@ type DraftsAction = DraftUpdateAction; type LoadingAction = DeadQueueAction | InitialFetchStartAction | InitialFetchCompleteAction; -type MessageAction = MessageFetchStartAction | MessageFetchCompleteAction; +type MessageAction = MarkMessagesReadAction | MessageFetchStartAction | MessageFetchCompleteAction; type OutboxAction = MessageSendStartAction | MessageSendCompleteAction | DeleteOutboxMessageAction; diff --git a/src/boot/__tests__/reducers-test.js b/src/boot/__tests__/reducers-test.js index a56e5acefbf..a29b34c6102 100644 --- a/src/boot/__tests__/reducers-test.js +++ b/src/boot/__tests__/reducers-test.js @@ -4,6 +4,7 @@ import { discardKeys, storeKeys, cacheKeys } from '../../boot/store'; describe('reducers', () => { test('reducers return the default states on unknown action', () => { + // $FlowFixMe bogus action object expect(() => reducers({}, { type: 'UNKNOWN_ACTION' })).not.toThrow(); }); diff --git a/src/caughtup/__tests__/caughtUpReducers-test.js b/src/caughtup/__tests__/caughtUpReducers-test.js index 9eb91364edd..0016038dc24 100644 --- a/src/caughtup/__tests__/caughtUpReducers-test.js +++ b/src/caughtup/__tests__/caughtUpReducers-test.js @@ -26,6 +26,7 @@ describe('caughtUpReducers', () => { narrow: HOME_NARROW, }); + // $FlowFixMe bogus action object const newState = caughtUpReducers(initialState, action); expect(newState).toBe(initialState); diff --git a/src/loading/__tests__/loadingReducer-test.js b/src/loading/__tests__/loadingReducer-test.js index 2bda1ce5c13..e47138706ce 100644 --- a/src/loading/__tests__/loadingReducer-test.js +++ b/src/loading/__tests__/loadingReducer-test.js @@ -17,6 +17,7 @@ describe('loadingReducers', () => { const action = deepFreeze({ type: ACCOUNT_SWITCH, + index: 1, }); const expectedState = {