Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Flow-related work on the path to RN v0.64 upgrade, part 1. #4518

Merged
merged 15 commits into from
Mar 10, 2021
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
types: Make object types with indexer properties exact, in our code.
If all has gone to plan, I've improved *all* relevant object types
in our own code this way (not including libdefs). I cast a wide net
for all indexer properties, with a global search for

  \]:

in *.js files outside the flow-typed directory. Some results weren't
indexer properties, but among the ones that were, I made the inexact
ones exact.
chrisbobbe authored and gnprice committed Mar 10, 2021

Verified

This commit was signed with the committer’s verified signature. The key has expired.
juliusknorr Julius Knorr
commit 8bd409626c81f5a378d490a804cd2f6de5c1bc0a
2 changes: 1 addition & 1 deletion src/__tests__/lib/exampleData.js
Original file line number Diff line number Diff line change
@@ -674,7 +674,7 @@ export const action = deepFreeze({
// annotate `action` itself, because we want to keep the information of
// which one has which specific type.)
/* eslint-disable-next-line no-unused-expressions */
(action: { [string]: Action });
(action: {| [string]: Action |});

/* ========================================================================
* Action fragments
6 changes: 3 additions & 3 deletions src/api/initialDataTypes.js
Original file line number Diff line number Diff line change
@@ -38,9 +38,9 @@ export type InitialDataPresence = {|
presences: {| [email: string]: UserPresence |},
|};

export type AvailableVideoChatProviders = {
export type AvailableVideoChatProviders = {|
[providerName: string]: {| name: string, id: number |},
};
|};

export type InitialDataRealm = {|
jitsi_server_url?: string,
@@ -171,7 +171,7 @@ export type InitialDataSubscription = {|
export type InitialDataUpdateDisplaySettings = {|
default_language: string,
emojiset: string,
emojiset_choices: { [string]: string },
emojiset_choices: {| [string]: string |},
high_contrast_mode: boolean,
left_side_userlist: boolean,
night_mode: boolean,
6 changes: 3 additions & 3 deletions src/api/modelTypes.js
Original file line number Diff line number Diff line change
@@ -30,9 +30,9 @@ export type ImageEmojiType = $ReadOnly<{|
source_url: string,
|}>;

export type RealmEmojiById = $ReadOnly<{
export type RealmEmojiById = $ReadOnly<{|
[id: string]: ImageEmojiType,
}>;
|}>;

export type RealmFilter = [string, string, number];

@@ -462,7 +462,7 @@ export type Submessage = $ReadOnly<{|
* `EVENT_NEW_MESSAGE` Redux action for the event;
* * `messages: Message[]` in a `/messages` (our `getMessages`) response,
* and our resulting `MESSAGE_FETCH_COMPLETE` Redux action;
* * `messages: { [id]: Message }` in our global Redux state.
* * `messages: {| [id]: Message |}` in our global Redux state.
*
* References include:
* * the two example events at https://zulip.com/api/get-events-from-queue
2 changes: 1 addition & 1 deletion src/boot/store.js
Original file line number Diff line number Diff line change
@@ -106,7 +106,7 @@ function dropCache(state: GlobalState): $Shape<GlobalState> {
* a version number to track which migrations are already reflected in it,
* so that each only has to be run once.
*/
const migrations: { [string]: (GlobalState) => GlobalState } = {
const migrations: {| [string]: (GlobalState) => GlobalState |} = {
// The type is a lie, in several ways:
// * The actual object contains only the properties we persist:
// those in `storeKeys` and `cacheKeys`, but not `discardKeys`.
2 changes: 1 addition & 1 deletion src/directSelectors.js
Original file line number Diff line number Diff line change
@@ -63,7 +63,7 @@ export const getFetching = (state: GlobalState): FetchingState => state.fetching

export const getFlags = (state: GlobalState): FlagsState => state.flags;

export const getReadFlags = (state: GlobalState): { [messageId: number]: boolean } =>
export const getReadFlags = (state: GlobalState): {| [messageId: number]: boolean |} =>
state.flags.read;

export const getAllNarrows = (state: GlobalState): NarrowsState => state.narrows;
4 changes: 2 additions & 2 deletions src/emoji/codePointMap.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* @flow strict-local */

/** Maps certain emoji to substitutes, for us to show instead. */
export const override: { [code: string]: string } = {
export const override: {| [code: string]: string |} = {
// :check_mark: -> :check: because the former is invisible on a light
// background, i.e. when not in night mode.
'2714': '2705',
@@ -19,7 +19,7 @@ export const override: { [code: string]: string } = {
* Reaction.emoji_code here:
* https://github.com/zulip/zulip/blob/master/zerver/models.py
*/
export const unicodeCodeByName: { [name: string]: string } = {
export const unicodeCodeByName: {| [name: string]: string |} = {
'+1': '1f44d',
'-1': '1f44e',
'0': '0030-20e3',
2 changes: 1 addition & 1 deletion src/emoji/data.js
Original file line number Diff line number Diff line change
@@ -35,7 +35,7 @@ export const codeToEmojiMap = objectFromEntries<string, string>(
*/
export const getFilteredEmojis = (
query: string,
activeImageEmojiByName: $ReadOnly<{ [string]: ImageEmojiType }>,
activeImageEmojiByName: $ReadOnly<{| [string]: ImageEmojiType |}>,
): $ReadOnlyArray<{| emoji_type: EmojiType, name: string, code: string |}> => {
// We start by making a map from matching emoji names to a number
// representing how good a match it is: 0 for a prefix match, 1 for a
8 changes: 4 additions & 4 deletions src/emoji/emojiSelectors.js
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@ export const getAllImageEmojiById: Selector<RealmEmojiById> = createSelector(
getIdentity,
getRawRealmEmoji,
(identity, realmEmoji) => {
const result: { [string]: ImageEmojiType } = {};
const result: {| [string]: ImageEmojiType |} = {};
[realmEmoji, zulipExtraEmojiMap].forEach(emojis => {
Object.keys(emojis).forEach(id => {
result[id] = {
@@ -26,7 +26,7 @@ export const getAllImageEmojiById: Selector<RealmEmojiById> = createSelector(
export const getActiveImageEmojiById: Selector<RealmEmojiById> = createSelector(
getAllImageEmojiById,
emojis => {
const result: { [string]: ImageEmojiType } = {};
const result: {| [string]: ImageEmojiType |} = {};
Object.keys(emojis).forEach(id => {
if (!emojis[id].deactivated) {
result[id] = emojis[id];
@@ -36,12 +36,12 @@ export const getActiveImageEmojiById: Selector<RealmEmojiById> = createSelector(
},
);

export const getAllImageEmojiByCode: Selector<{ [string]: ImageEmojiType }> = createSelector(
export const getAllImageEmojiByCode: Selector<{| [string]: ImageEmojiType |}> = createSelector(
getAllImageEmojiById,
emojis => objectFromEntries(Object.keys(emojis).map(id => [emojis[id].code, emojis[id]])),
);

export const getActiveImageEmojiByName: Selector<{ [string]: ImageEmojiType }> = createSelector(
export const getActiveImageEmojiByName: Selector<{| [string]: ImageEmojiType |}> = createSelector(
getActiveImageEmojiById,
emojis => objectFromEntries(Object.keys(emojis).map(id => [emojis[id].name, emojis[id]])),
);
2 changes: 1 addition & 1 deletion src/emoji/zulipExtraEmojiMap.js
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@ import type { ImageEmojiType } from '../types';
* so that both emoji type can be handled in similiar way
* thus id has no meaning here
*/
const zulipExtraEmojiMap: { [id: string]: ImageEmojiType } = {
const zulipExtraEmojiMap: {| [id: string]: ImageEmojiType |} = {
zulip: {
deactivated: false,
code: 'zulip',
4 changes: 2 additions & 2 deletions src/jsBackport.js
Original file line number Diff line number Diff line change
@@ -18,8 +18,8 @@
* implement and is all we happened to need. Would be nice to extend to
* iterables.
*/
export function objectFromEntries<+K, +V>(entries: $ReadOnlyArray<[K, V]>): { [K]: V } {
const obj = ({}: { [K]: V });
export function objectFromEntries<+K, +V>(entries: $ReadOnlyArray<[K, V]>): {| [K]: V |} {
const obj = ({}: {| [K]: V |});
entries.forEach(entry => {
// ESLint bug? I don't understand how this rule even applies to this line.
// eslint-disable-next-line prefer-destructuring
2 changes: 1 addition & 1 deletion src/message/messageActionSheet.js
Original file line number Diff line number Diff line change
@@ -237,7 +237,7 @@ const allButtonsRaw = {

type ButtonCode = $Keys<typeof allButtonsRaw>;

const allButtons: { [ButtonCode]: ButtonDescription } = allButtonsRaw;
const allButtons: {| [ButtonCode]: ButtonDescription |} = allButtonsRaw;

type ConstructSheetParams<MsgType: Message | Outbox = Message | Outbox> = {|
backgroundData: BackgroundData,
4 changes: 2 additions & 2 deletions src/pm-conversations/pmConversationsSelectors.js
Original file line number Diff line number Diff line change
@@ -38,8 +38,8 @@ export const getRecentConversationsLegacy: Selector<PmConversationData[]> = crea
(
ownUserId,
messages: Message[],
unreadPms: { [number]: number },
unreadHuddles: { [string]: number },
unreadPms: {| [number]: number |},
unreadHuddles: {| [string]: number |},
allUsersById,
): PmConversationData[] => {
const items = messages
4 changes: 2 additions & 2 deletions src/redux-persist-migrate/index.js
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@ const processKey = key => {
/* eslint-disable no-use-before-define */

export default function createMigration(
manifest: { [string]: (State) => State },
manifest: {| [string]: (State) => State |},
versionSelector: string | (State => number | string | void),
versionSetter?: (State, number) => State,
): StoreEnhancer<State, Action, Dispatch<Action>> {
@@ -46,7 +46,7 @@ export default function createMigration(
}

export function createMigrationImpl(
manifest: { [string]: (State) => State },
manifest: {| [string]: (State) => State |},
versionSelector: State => number | string | void,
versionSetter: (State, number) => State,
): StoreEnhancer<State, Action, Dispatch<Action>> {
47 changes: 22 additions & 25 deletions src/reduxTypes.js
Original file line number Diff line number Diff line change
@@ -73,20 +73,18 @@ export type CaughtUp = {|
*
* See `CaughtUp` for details on what each value means.
*/
export type CaughtUpState = {
// TODO(flow-v0.126): Should be exact. See note in src/utils/jsonable.js.
export type CaughtUpState = {|
[narrow: string]: CaughtUp,
};
|};

/**
* The user's draft message, if any, in each conversation.
*
* The keys correspond to the keys in `NarrowsState`.
*/
export type DraftsState = {
// TODO(flow-v0.126): Should be exact. See note in src/utils/jsonable.js.
export type DraftsState = {|
[narrow: string]: string,
};
|};

export type Fetching = {|
older: boolean,
@@ -100,10 +98,9 @@ export type Fetching = {|
*
* See also: `CaughtUpState`, `NarrowsState`.
*/
export type FetchingState = {
// TODO(flow-v0.126): Should be exact. See note in src/utils/jsonable.js.
export type FetchingState = {|
[narrow: string]: Fetching,
};
|};

/**
* The message flags corresponding to all the messages in `MessagesState`.
@@ -112,18 +109,18 @@ export type FetchingState = {
* incomplete, always in exactly the same way that `MessagesState` is.
*/
export type FlagsState = {|
read: { [messageId: number]: boolean },
starred: { [messageId: number]: boolean },
collapsed: { [messageId: number]: boolean },
mentioned: { [messageId: number]: boolean },
wildcard_mentioned: { [messageId: number]: boolean },
summarize_in_home: { [messageId: number]: boolean },
summarize_in_stream: { [messageId: number]: boolean },
force_expand: { [messageId: number]: boolean },
force_collapse: { [messageId: number]: boolean },
has_alert_word: { [messageId: number]: boolean },
historical: { [messageId: number]: boolean },
is_me_message: { [messageId: number]: boolean },
read: {| [messageId: number]: boolean |},
starred: {| [messageId: number]: boolean |},
collapsed: {| [messageId: number]: boolean |},
mentioned: {| [messageId: number]: boolean |},
wildcard_mentioned: {| [messageId: number]: boolean |},
summarize_in_home: {| [messageId: number]: boolean |},
summarize_in_stream: {| [messageId: number]: boolean |},
force_expand: {| [messageId: number]: boolean |},
force_collapse: {| [messageId: number]: boolean |},
has_alert_word: {| [messageId: number]: boolean |},
historical: {| [messageId: number]: boolean |},
is_me_message: {| [messageId: number]: boolean |},
|};

export type FlagName = $Keys<FlagsState>;
@@ -207,9 +204,9 @@ export type OutboxState = Outbox[];
* @prop (email) - Indexes over all users for which the app has received a
* presence status.
*/
export type PresenceState = {
export type PresenceState = {|
[email: string]: UserPresence,
};
|};

/**
* Configuration for a video chat provider, as specified by the server.
@@ -290,12 +287,12 @@ export type TopicsState = {|
[number]: Topic[],
|};

export type TypingState = {
export type TypingState = {|
[normalizedRecipients: string]: {
time: number,
userIds: UserId[],
},
};
|};

export type UserGroupsState = UserGroup[];

2 changes: 1 addition & 1 deletion src/streams/StreamList.js
Original file line number Diff line number Diff line change
@@ -21,7 +21,7 @@ type Props = $ReadOnly<{|
showDescriptions: boolean,
showSwitch: boolean,
streams: $ReadOnlyArray<PseudoSubscription>,
unreadByStream: $ReadOnly<{ [number]: number }>,
unreadByStream: $ReadOnly<{| [number]: number |}>,
onPress: (streamName: string) => void,
onSwitch?: (streamName: string, newValue: boolean) => void,
|}>;
2 changes: 1 addition & 1 deletion src/streams/SubscriptionsCard.js
Original file line number Diff line number Diff line change
@@ -24,7 +24,7 @@ const styles = createStyleSheet({

type SelectorProps = $ReadOnly<{|
subscriptions: Subscription[],
unreadByStream: $ReadOnly<{ [number]: number }>,
unreadByStream: $ReadOnly<{| [number]: number |}>,
|}>;

type Props = $ReadOnly<{|
2 changes: 1 addition & 1 deletion src/styles/theme.js
Original file line number Diff line number Diff line change
@@ -11,7 +11,7 @@ export type ThemeData = {|
dividerColor: string,
|};

export const themeData: { [name: ThemeName | 'light']: ThemeData } = {
export const themeData: {| [name: ThemeName | 'light']: ThemeData |} = {
night: {
color: 'hsl(210, 11%, 85%)',
backgroundColor: 'hsl(212, 28%, 18%)',
6 changes: 3 additions & 3 deletions src/types.js
Original file line number Diff line number Diff line change
@@ -236,7 +236,7 @@ export type MessageLike =
| $ReadOnly<Message>
| $ReadOnly<{
// $Shape<T> is unsound, per Flow docs, but $ReadOnly<$Shape<T>> is not
...$Shape<{ [$Keys<Message>]: void }>,
...$Shape<{| [$Keys<Message>]: void |}>,
sender_id?: UserId, // TODO: Drop this once required in Outbox.
...Outbox,
}>;
@@ -246,7 +246,7 @@ type IntlMessageFormatValue = string | number | boolean | null | void;

export type LocalizableText =
| string
| { text: string, values?: { [string]: IntlMessageFormatValue } };
| { text: string, values?: {| [string]: IntlMessageFormatValue |} };

/**
* Usually called `_`, and invoked like `_('Message')` -> `'Nachricht'`.
@@ -264,7 +264,7 @@ export type LocalizableText =
* @prop intl - The full react-intl API, for more complex situations.
*/
export type GetText = {
(message: string, values?: { [string]: IntlMessageFormatValue }): string,
(message: string, values?: {| [string]: IntlMessageFormatValue |}): string,
intl: IntlShape,
};

12 changes: 6 additions & 6 deletions src/unread/unreadSelectors.js
Original file line number Diff line number Diff line change
@@ -13,12 +13,12 @@ import { pmUnreadsKeyFromPmKeyIds } from '../utils/recipient';
import { getUnreadStreams, getUnreadPms, getUnreadHuddles, getUnreadMentions } from './unreadModel';

/** The number of unreads in each stream, excluding muted topics, by stream ID. */
export const getUnreadByStream: Selector<{ [number]: number }> = createSelector(
export const getUnreadByStream: Selector<{| [number]: number |}> = createSelector(
getUnreadStreams,
getSubscriptionsById,
getMute,
(unreadStreams, subscriptionsById, mute) => {
const totals = ({}: { [number]: number });
const totals = ({}: {| [number]: number |});
unreadStreams.forEach(stream => {
if (!totals[stream.stream_id]) {
totals[stream.stream_id] = 0;
@@ -50,10 +50,10 @@ export const getUnreadStreamTotal: Selector<number> = createSelector(
*
* See also `getUnreadByHuddles`, for group PM threads.
*/
export const getUnreadByPms: Selector<{ [number]: number }> = createSelector(
export const getUnreadByPms: Selector<{| [number]: number |}> = createSelector(
getUnreadPms,
unreadPms => {
const totals = ({}: { [number]: number });
const totals = ({}: {| [number]: number |});
unreadPms.forEach(pm => {
totals[pm.sender_id] = totals[pm.sender_id] || 0 + pm.unread_message_ids.length;
});
@@ -80,10 +80,10 @@ export const getUnreadPmsTotal: Selector<number> = createSelector(
*
* See also `getUnreadByPms`, for 1:1 PM threads.
*/
export const getUnreadByHuddles: Selector<{ [string]: number }> = createSelector(
export const getUnreadByHuddles: Selector<{| [string]: number |}> = createSelector(
getUnreadHuddles,
unreadHuddles => {
const totals = ({}: { [string]: number });
const totals = ({}: {| [string]: number |});
unreadHuddles.forEach(huddle => {
totals[huddle.user_ids_string] =
totals[huddle.user_ids_string] || 0 + huddle.unread_message_ids.length;
Loading