Skip to content

Commit

Permalink
actions: Clarify to Flow that these constants are type-tags.
Browse files Browse the repository at this point in the history
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`.
  • Loading branch information
gnprice committed Jan 11, 2019
1 parent ea2b119 commit e6868d8
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 85 deletions.
174 changes: 90 additions & 84 deletions src/actionConstants.js
Original file line number Diff line number Diff line change
@@ -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';
2 changes: 1 addition & 1 deletion src/actionTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
1 change: 1 addition & 0 deletions src/boot/__tests__/reducers-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();
});

Expand Down
1 change: 1 addition & 0 deletions src/caughtup/__tests__/caughtUpReducers-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ describe('caughtUpReducers', () => {
narrow: HOME_NARROW,
});

// $FlowFixMe bogus action object
const newState = caughtUpReducers(initialState, action);

expect(newState).toBe(initialState);
Expand Down
1 change: 1 addition & 0 deletions src/loading/__tests__/loadingReducer-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ describe('loadingReducers', () => {

const action = deepFreeze({
type: ACCOUNT_SWITCH,
index: 1,
});

const expectedState = {
Expand Down

0 comments on commit e6868d8

Please sign in to comment.