diff --git a/.flowconfig b/.flowconfig index a9265c30608..7da4b2c464f 100644 --- a/.flowconfig +++ b/.flowconfig @@ -35,6 +35,13 @@ node_modules/warning/.* [untyped] .*/node_modules/@react-native-community/cli/.*/.* +; TODO: Remove this line when RN v0.64 upgrade is complete. We took +; Flow from v0.122 to v0.125 before finishing the upgrade, to more +; gradually handle the deprecation of `suppress_comment`. When we did +; that mini Flow upgrade, one error in RN's code was flagged, and it +; was in this module. +.*/node_modules/react-native/Libraries/ReactNative/PaperUIManager.js + [include] ; Effectively this line warns Flow that this path might be a symlink ; (because the developer might be using `yarn link` to have this point into @@ -115,11 +122,5 @@ module.file_ext=.js module.file_ext=.json module.file_ext=.ios.js -suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(\\)? *\\(site=[a-z,_]*react_native\\(_ios\\)?_\\(oss\\|fb\\)[a-z,_]*\\)?)\\) -suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(\\)? *\\(site=[a-z,_]*react_native\\(_ios\\)?_\\(oss\\|fb\\)[a-z,_]*\\)?)\\)?:? #[0-9]+ -suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy -suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError -suppress_comment=\\(.\\|\n\\)*\\$FlowMigrationFudge - [version] -^0.122.0 +^0.128.0 diff --git a/flow-typed/@react-navigation/bottom-tabs_v5.x.x.js b/flow-typed/@react-navigation/bottom-tabs_v5.x.x.js index a2804d8d8ee..0bf92f2365a 100644 --- a/flow-typed/@react-navigation/bottom-tabs_v5.x.x.js +++ b/flow-typed/@react-navigation/bottom-tabs_v5.x.x.js @@ -26,7 +26,7 @@ declare module '@react-navigation/bottom-tabs' { | false | '' | $ReadOnlyArray - | { [name: string]: any, ... }; + | {| [name: string]: any |}; declare type ViewStyleProp = StyleObj; declare type TextStyleProp = StyleObj; declare type AnimatedViewStyleProp = StyleObj; @@ -425,7 +425,7 @@ declare module '@react-navigation/bottom-tabs' { * Actions, state, etc. */ - declare export type ScreenParams = { +[key: string]: mixed, ... }; + declare export type ScreenParams = {| +[key: string]: mixed |}; declare export type BackAction = {| +type: 'GO_BACK', @@ -474,7 +474,7 @@ declare module '@react-navigation/bottom-tabs' { declare export type GenericNavigationAction = {| +type: string, - +payload?: { +[key: string]: mixed, ... }, + +payload?: {| +[key: string]: mixed |}, +source?: string, +target?: string, |}; @@ -540,10 +540,9 @@ declare module '@react-navigation/bottom-tabs' { declare type ActionCreators< State: NavigationState, Action: GenericNavigationAction, - > = { + > = {| +[key: string]: (...args: any) => (Action | State => Action), - ... - }; + |}; declare export type DefaultRouterOptions = { +initialRouteName?: string, @@ -556,7 +555,7 @@ declare module '@react-navigation/bottom-tabs' { RouterOptions: DefaultRouterOptions, > = (options: RouterOptions) => Router; - declare export type ParamListBase = { +[key: string]: ?ScreenParams, ... }; + declare export type ParamListBase = {| +[key: string]: ?ScreenParams |}; declare export type RouterConfigOptions = {| +routeNames: $ReadOnlyArray, @@ -714,13 +713,12 @@ declare module '@react-navigation/bottom-tabs' { * Events */ - declare export type EventMapBase = { + declare export type EventMapBase = {| +[name: string]: {| +data?: mixed, +canPreventDefault?: boolean, |}, - ... - }; + |}; declare type EventPreventDefaultProperties = $If< Test, {| +defaultPrevented: boolean, +preventDefault: () => void |}, @@ -1910,7 +1908,7 @@ declare module '@react-navigation/bottom-tabs' { declare export type ContainerEventMap = {| ...GlobalEventMap, +options: {| - +data: {| +options: { +[key: string]: mixed, ... } |}, + +data: {| +options: {| +[key: string]: mixed |} |}, +canPreventDefault: false, |}, +__unsafe_action__: {| diff --git a/flow-typed/@react-navigation/drawer_v5.x.x.js b/flow-typed/@react-navigation/drawer_v5.x.x.js index b2cf468edd1..fa861bcf09e 100644 --- a/flow-typed/@react-navigation/drawer_v5.x.x.js +++ b/flow-typed/@react-navigation/drawer_v5.x.x.js @@ -26,7 +26,7 @@ declare module '@react-navigation/drawer' { | false | '' | $ReadOnlyArray - | { [name: string]: any, ... }; + | {| [name: string]: any |}; declare type ViewStyleProp = StyleObj; declare type TextStyleProp = StyleObj; declare type AnimatedViewStyleProp = StyleObj; @@ -425,7 +425,7 @@ declare module '@react-navigation/drawer' { * Actions, state, etc. */ - declare export type ScreenParams = { +[key: string]: mixed, ... }; + declare export type ScreenParams = {| +[key: string]: mixed |}; declare export type BackAction = {| +type: 'GO_BACK', @@ -474,7 +474,7 @@ declare module '@react-navigation/drawer' { declare export type GenericNavigationAction = {| +type: string, - +payload?: { +[key: string]: mixed, ... }, + +payload?: {| +[key: string]: mixed |}, +source?: string, +target?: string, |}; @@ -540,10 +540,9 @@ declare module '@react-navigation/drawer' { declare type ActionCreators< State: NavigationState, Action: GenericNavigationAction, - > = { + > = {| +[key: string]: (...args: any) => (Action | State => Action), - ... - }; + |}; declare export type DefaultRouterOptions = { +initialRouteName?: string, @@ -556,7 +555,7 @@ declare module '@react-navigation/drawer' { RouterOptions: DefaultRouterOptions, > = (options: RouterOptions) => Router; - declare export type ParamListBase = { +[key: string]: ?ScreenParams, ... }; + declare export type ParamListBase = {| +[key: string]: ?ScreenParams |}; declare export type RouterConfigOptions = {| +routeNames: $ReadOnlyArray, @@ -714,13 +713,12 @@ declare module '@react-navigation/drawer' { * Events */ - declare export type EventMapBase = { + declare export type EventMapBase = {| +[name: string]: {| +data?: mixed, +canPreventDefault?: boolean, |}, - ... - }; + |}; declare type EventPreventDefaultProperties = $If< Test, {| +defaultPrevented: boolean, +preventDefault: () => void |}, @@ -1910,7 +1908,7 @@ declare module '@react-navigation/drawer' { declare export type ContainerEventMap = {| ...GlobalEventMap, +options: {| - +data: {| +options: { +[key: string]: mixed, ... } |}, + +data: {| +options: {| +[key: string]: mixed |} |}, +canPreventDefault: false, |}, +__unsafe_action__: {| diff --git a/flow-typed/@react-navigation/material-top-tabs_v5.x.x.js b/flow-typed/@react-navigation/material-top-tabs_v5.x.x.js index 300781d34e4..9f33f0eab5e 100644 --- a/flow-typed/@react-navigation/material-top-tabs_v5.x.x.js +++ b/flow-typed/@react-navigation/material-top-tabs_v5.x.x.js @@ -26,7 +26,7 @@ declare module '@react-navigation/material-top-tabs' { | false | '' | $ReadOnlyArray - | { [name: string]: any, ... }; + | {| [name: string]: any |}; declare type ViewStyleProp = StyleObj; declare type TextStyleProp = StyleObj; declare type AnimatedViewStyleProp = StyleObj; @@ -425,7 +425,7 @@ declare module '@react-navigation/material-top-tabs' { * Actions, state, etc. */ - declare export type ScreenParams = { +[key: string]: mixed, ... }; + declare export type ScreenParams = {| +[key: string]: mixed |}; declare export type BackAction = {| +type: 'GO_BACK', @@ -474,7 +474,7 @@ declare module '@react-navigation/material-top-tabs' { declare export type GenericNavigationAction = {| +type: string, - +payload?: { +[key: string]: mixed, ... }, + +payload?: {| +[key: string]: mixed |}, +source?: string, +target?: string, |}; @@ -540,10 +540,9 @@ declare module '@react-navigation/material-top-tabs' { declare type ActionCreators< State: NavigationState, Action: GenericNavigationAction, - > = { + > = {| +[key: string]: (...args: any) => (Action | State => Action), - ... - }; + |}; declare export type DefaultRouterOptions = { +initialRouteName?: string, @@ -556,7 +555,7 @@ declare module '@react-navigation/material-top-tabs' { RouterOptions: DefaultRouterOptions, > = (options: RouterOptions) => Router; - declare export type ParamListBase = { +[key: string]: ?ScreenParams, ... }; + declare export type ParamListBase = {| +[key: string]: ?ScreenParams |}; declare export type RouterConfigOptions = {| +routeNames: $ReadOnlyArray, @@ -714,13 +713,12 @@ declare module '@react-navigation/material-top-tabs' { * Events */ - declare export type EventMapBase = { + declare export type EventMapBase = {| +[name: string]: {| +data?: mixed, +canPreventDefault?: boolean, |}, - ... - }; + |}; declare type EventPreventDefaultProperties = $If< Test, {| +defaultPrevented: boolean, +preventDefault: () => void |}, @@ -1910,7 +1908,7 @@ declare module '@react-navigation/material-top-tabs' { declare export type ContainerEventMap = {| ...GlobalEventMap, +options: {| - +data: {| +options: { +[key: string]: mixed, ... } |}, + +data: {| +options: {| +[key: string]: mixed |} |}, +canPreventDefault: false, |}, +__unsafe_action__: {| diff --git a/flow-typed/@react-navigation/native_v5.x.x.js b/flow-typed/@react-navigation/native_v5.x.x.js index f23b9b922cd..ae0d0fdb15f 100644 --- a/flow-typed/@react-navigation/native_v5.x.x.js +++ b/flow-typed/@react-navigation/native_v5.x.x.js @@ -26,7 +26,7 @@ declare module '@react-navigation/native' { | false | '' | $ReadOnlyArray - | { [name: string]: any, ... }; + | {| [name: string]: any |}; declare type ViewStyleProp = StyleObj; declare type TextStyleProp = StyleObj; declare type AnimatedViewStyleProp = StyleObj; @@ -425,7 +425,7 @@ declare module '@react-navigation/native' { * Actions, state, etc. */ - declare export type ScreenParams = { +[key: string]: mixed, ... }; + declare export type ScreenParams = {| +[key: string]: mixed |}; declare export type BackAction = {| +type: 'GO_BACK', @@ -474,7 +474,7 @@ declare module '@react-navigation/native' { declare export type GenericNavigationAction = {| +type: string, - +payload?: { +[key: string]: mixed, ... }, + +payload?: {| +[key: string]: mixed |}, +source?: string, +target?: string, |}; @@ -540,10 +540,9 @@ declare module '@react-navigation/native' { declare type ActionCreators< State: NavigationState, Action: GenericNavigationAction, - > = { + > = {| +[key: string]: (...args: any) => (Action | State => Action), - ... - }; + |}; declare export type DefaultRouterOptions = { +initialRouteName?: string, @@ -556,7 +555,7 @@ declare module '@react-navigation/native' { RouterOptions: DefaultRouterOptions, > = (options: RouterOptions) => Router; - declare export type ParamListBase = { +[key: string]: ?ScreenParams, ... }; + declare export type ParamListBase = {| +[key: string]: ?ScreenParams |}; declare export type RouterConfigOptions = {| +routeNames: $ReadOnlyArray, @@ -714,13 +713,12 @@ declare module '@react-navigation/native' { * Events */ - declare export type EventMapBase = { + declare export type EventMapBase = {| +[name: string]: {| +data?: mixed, +canPreventDefault?: boolean, |}, - ... - }; + |}; declare type EventPreventDefaultProperties = $If< Test, {| +defaultPrevented: boolean, +preventDefault: () => void |}, @@ -1910,7 +1908,7 @@ declare module '@react-navigation/native' { declare export type ContainerEventMap = {| ...GlobalEventMap, +options: {| - +data: {| +options: { +[key: string]: mixed, ... } |}, + +data: {| +options: {| +[key: string]: mixed |} |}, +canPreventDefault: false, |}, +__unsafe_action__: {| diff --git a/flow-typed/@react-navigation/stack_v5.x.x.js b/flow-typed/@react-navigation/stack_v5.x.x.js index 9e82f8e04ec..958d817e2ac 100644 --- a/flow-typed/@react-navigation/stack_v5.x.x.js +++ b/flow-typed/@react-navigation/stack_v5.x.x.js @@ -26,7 +26,7 @@ declare module '@react-navigation/stack' { | false | '' | $ReadOnlyArray - | { [name: string]: any, ... }; + | {| [name: string]: any |}; declare type ViewStyleProp = StyleObj; declare type TextStyleProp = StyleObj; declare type AnimatedViewStyleProp = StyleObj; @@ -425,7 +425,7 @@ declare module '@react-navigation/stack' { * Actions, state, etc. */ - declare export type ScreenParams = { +[key: string]: mixed, ... }; + declare export type ScreenParams = {| +[key: string]: mixed |}; declare export type BackAction = {| +type: 'GO_BACK', @@ -474,7 +474,7 @@ declare module '@react-navigation/stack' { declare export type GenericNavigationAction = {| +type: string, - +payload?: { +[key: string]: mixed, ... }, + +payload?: {| +[key: string]: mixed |}, +source?: string, +target?: string, |}; @@ -540,10 +540,9 @@ declare module '@react-navigation/stack' { declare type ActionCreators< State: NavigationState, Action: GenericNavigationAction, - > = { + > = {| +[key: string]: (...args: any) => (Action | State => Action), - ... - }; + |}; declare export type DefaultRouterOptions = { +initialRouteName?: string, @@ -556,7 +555,7 @@ declare module '@react-navigation/stack' { RouterOptions: DefaultRouterOptions, > = (options: RouterOptions) => Router; - declare export type ParamListBase = { +[key: string]: ?ScreenParams, ... }; + declare export type ParamListBase = {| +[key: string]: ?ScreenParams |}; declare export type RouterConfigOptions = {| +routeNames: $ReadOnlyArray, @@ -714,13 +713,12 @@ declare module '@react-navigation/stack' { * Events */ - declare export type EventMapBase = { + declare export type EventMapBase = {| +[name: string]: {| +data?: mixed, +canPreventDefault?: boolean, |}, - ... - }; + |}; declare type EventPreventDefaultProperties = $If< Test, {| +defaultPrevented: boolean, +preventDefault: () => void |}, @@ -1910,7 +1908,7 @@ declare module '@react-navigation/stack' { declare export type ContainerEventMap = {| ...GlobalEventMap, +options: {| - +data: {| +options: { +[key: string]: mixed, ... } |}, + +data: {| +options: {| +[key: string]: mixed |} |}, +canPreventDefault: false, |}, +__unsafe_action__: {| diff --git a/flow-typed/@sentry/react-native_v2.x.x.js b/flow-typed/@sentry/react-native_v2.x.x.js index 6a6d88d38c8..646cd814607 100644 --- a/flow-typed/@sentry/react-native_v2.x.x.js +++ b/flow-typed/@sentry/react-native_v2.x.x.js @@ -1,5 +1,4 @@ declare module '@sentry/react-native' { - declare type Primitive = | number | string @@ -57,7 +56,7 @@ declare module '@sentry/react-native' { event_id?: string, message?: string, timestamp?: number, - start_timestamp?: number; + start_timestamp?: number, level?: SeverityType, platform?: string, logger?: string, @@ -68,14 +67,14 @@ declare module '@sentry/react-native' { // sdk?: SdkInfo, // request?: Request, transaction?: string, - modules?: { [key: string]: string }, + modules?: {| [key: string]: string |}, fingerprint?: string[], // exception?: { values?: Exception[], }, // stacktrace?: Stacktrace, breadcrumbs?: Breadcrumb[], - // contexts?: { [key: string]: object }, - tags?: { [key: string]: Primitive }, - extra?: { [key: string]: any }, + // contexts?: {| [key: string]: object |}, + tags?: {| [key: string]: Primitive |}, + extra?: {| [key: string]: any |}, // user?: User, type?: EventType, |}; @@ -86,7 +85,7 @@ declare module '@sentry/react-native' { // Taken from @sentry/types/src/event.ts. declare export type EventHint = {| event_id?: string, - captureContext?: CaptureContext; + captureContext?: CaptureContext, syntheticException?: Error | null, originalException?: Error | string | null, data?: mixed, @@ -99,9 +98,9 @@ declare module '@sentry/react-native' { event_id?: string, category?: string, message?: string, - data?: { - [key: string]: mixed; - }, + data?: {| + [key: string]: mixed, + |}, timestamp?: number, |}; @@ -120,9 +119,9 @@ declare module '@sentry/react-native' { * Set an object that will be merged sent as tags data with the event. * @param tags Tags context object to merge into current context. */ - setTags(tags: { + setTags(tags: {| +[key: string]: Primitive, - }): this; + |}): this; /** * Set key:value that will be sent as tags data with the event. * @param key String key of tag @@ -140,7 +139,7 @@ declare module '@sentry/react-native' { * Set an object that will be merged sent as extra data with the event. * @param extras Extras object to merge into current context. */ - setExtras(extras: { +[key: string]: any }): this; + setExtras(extras: {| +[key: string]: any |}): this; } declare export type CaptureContext = Scope | Partial | ((scope: Scope) => Scope); @@ -160,8 +159,14 @@ declare module '@sentry/react-native' { // https://docs.sentry.io/development/sdk-dev/unified-api/#static-api // // Taken from @sentry/minimal/src/index.ts. - declare export function captureException(exception: mixed, captureContext?: CaptureContext): string; - declare export function captureMessage(message: string, captureContext?: CaptureContext | SeverityType): string; + declare export function captureException( + exception: mixed, + captureContext?: CaptureContext, + ): string; + declare export function captureMessage( + message: string, + captureContext?: CaptureContext | SeverityType, + ): string; declare export function addBreadcrumb(breadcrumb: Breadcrumb): void; /* Modifies the current scope. Avoid in favor of `withScope` wherever diff --git a/flow-typed/jest_v26.x.x.js b/flow-typed/jest_v26.x.x.js index 20876ccf00b..cd4f54928d0 100644 --- a/flow-typed/jest_v26.x.x.js +++ b/flow-typed/jest_v26.x.x.js @@ -239,8 +239,8 @@ type DomTestingLibraryType = { toHaveAttribute(attr: string, value?: any): void, toHaveClass(...classNames: string[]): void, toHaveFocus(): void, - toHaveFormValues(expectedValues: { [name: string]: any, ... }): void, - toHaveStyle(css: string | { [name: string]: any, ... }): void, + toHaveFormValues(expectedValues: {| [name: string]: any |}): void, + toHaveStyle(css: string | {| [name: string]: any |}): void, toHaveTextContent(text: string | RegExp, options?: {| normalizeWhitespace: boolean |}): void, toHaveValue(value?: string | string[] | number): void, @@ -262,7 +262,7 @@ type JestJQueryMatchersType = { toHaveText(text: string | RegExp): void, toHaveData(key: string, val?: any): void, toHaveValue(val: any): void, - toHaveCss(css: { [key: string]: any, ... }): void, + toHaveCss(css: {| [key: string]: any |}): void, toBeChecked(): void, toBeDisabled(): void, toBeEmpty(): void, @@ -1141,7 +1141,7 @@ declare var expect: { JestExtendedMatchersType & SnapshotDiffType, /** Add additional Jasmine matchers to Jest's roster */ - extend(matchers: { [name: string]: JestMatcher, ... }): void, + extend(matchers: {| [name: string]: JestMatcher |}): void, /** Add a module that formats application-specific data structures. */ addSnapshotSerializer(pluginModule: JestPrettyFormatPlugin): void, assertions(expectedAssertions: number): void, @@ -1184,7 +1184,7 @@ declare var jasmine: { createSpyObj( baseName: string, methodNames: Array, - ): { [methodName: string]: JestSpyType, ... }, + ): {| [methodName: string]: JestSpyType |}, objectContaining(value: Object): Object, stringMatching(value: string): string, ... diff --git a/flow-typed/react-intl_vx.x.x.js b/flow-typed/react-intl_vx.x.x.js index 4e2c9909149..6ed1c6d7e22 100644 --- a/flow-typed/react-intl_vx.x.x.js +++ b/flow-typed/react-intl_vx.x.x.js @@ -36,7 +36,7 @@ declare module 'react-intl' { format?: string; } declare export type CustomFormats = { - relative?: { [key: string]: IntlRelativeTimeFormatOptions, ... }, + relative?: {| [key: string]: IntlRelativeTimeFormatOptions |}, ... } & $Rest; declare type DateElement = SimpleFormatElement; @@ -45,8 +45,7 @@ declare module 'react-intl' { dateStyle?: 'full' | 'long' | 'medium' | 'short', timeStyle?: 'full' | 'long' | 'medium' | 'short', fractionalSecondDigits?: number, - calendar?: - | 'buddhist' + calendar?: | 'buddhist' | 'chinese' | 'coptic' | 'ethiopia' @@ -75,10 +74,9 @@ declare module 'react-intl' { | 'textComponent' | 'defaultLocale' | 'defaultFormats' - | 'onError', - >; + | 'onError', >; declare export function defineMessage(msg: T): T; - declare export function defineMessages, T, U: { [key: K]: T, ... }>(msgs: U): U; + declare export function defineMessages, T, U: {| [key: K]: T |}>(msgs: U): U; declare class DisplayNames { constructor(locales?: string | string[], options?: DisplayNamesOptions): this; static supportedLocalesOf( @@ -86,9 +84,9 @@ declare module 'react-intl' { options?: Pick, ): string[]; static __addLocaleData(...data: DisplayNamesLocaleData[]): void; - of(code: string | number | { [key: string]: any }): string | void; + of(code: string | number | {| [key: string]: any |}): string | void; resolvedOptions(): DisplayNamesResolvedOptions; - static localeData: { [key: string]: DisplayNamesData, ... }; + static localeData: {| [key: string]: DisplayNamesData |}; static +polyfilled: any; // true } declare interface DisplayNamesData { @@ -101,27 +99,27 @@ declare module 'react-intl' { * Maps language subtag like `zh-CN` to their display names. */ language: { - narrow: { [key: LanguageTag]: string, ... }, - short: { [key: LanguageTag]: string, ... }, - long: { [key: LanguageTag]: string, ... }, + narrow: {| [key: LanguageTag]: string |}, + short: {| [key: LanguageTag]: string |}, + long: {| [key: LanguageTag]: string |}, ... }, region: { - narrow: { [key: RegionCode]: string, ... }, - short: { [key: RegionCode]: string, ... }, - long: { [key: RegionCode]: string, ... }, + narrow: {| [key: RegionCode]: string |}, + short: {| [key: RegionCode]: string |}, + long: {| [key: RegionCode]: string |}, ... }, script: { - narrow: { [key: ScriptCode]: string, ... }, - short: { [key: ScriptCode]: string, ... }, - long: { [key: ScriptCode]: string, ... }, + narrow: {| [key: ScriptCode]: string |}, + short: {| [key: ScriptCode]: string |}, + long: {| [key: ScriptCode]: string |}, ... }, currency: { - narrow: { [key: CurrencyCode]: string, ... }, - short: { [key: CurrencyCode]: string, ... }, - long: { [key: CurrencyCode]: string, ... }, + narrow: {| [key: CurrencyCode]: string |}, + short: {| [key: CurrencyCode]: string |}, + long: {| [key: CurrencyCode]: string |}, ... }, ... @@ -200,13 +198,12 @@ declare module 'react-intl' { CustomFormatConfig; declare export type FormatRelativeTimeOptions = Exclude< IntlRelativeTimeFormatOptions, - 'localeMatcher', - > & + 'localeMatcher', > & CustomFormatConfig; declare interface Formats { - number: { [key: string]: Intl.NumberFormatOptions, ... }; - date: { [key: string]: Intl.DateTimeFormatOptions, ... }; - time: { [key: string]: Intl.DateTimeFormatOptions, ... }; + number: {| [key: string]: Intl.NumberFormatOptions |}; + date: {| [key: string]: Intl.DateTimeFormatOptions |}; + time: {| [key: string]: Intl.DateTimeFormatOptions |}; } declare type FormattableUnit = Unit | Units; declare export var FormattedDate: React$StatelessFunctionalComponent< @@ -214,35 +211,30 @@ declare module 'react-intl' { CustomFormatConfig & { value: string | number | Date | void, ... - }, - >; + }, >; declare export var FormattedDateParts: React$StatelessFunctionalComponent< FormatDateOptions & { value: $ElementType>, 0> | string, children(val: Intl.DateTimeFormatPart[]): React_2.ReactElement<> | null, ... - }, - >; + }, >; declare export var FormattedDisplayName: React$StatelessFunctionalComponent< DisplayNamesOptions & { - value: string | number | { [key: string]: any }, + value: string | number | {| [key: string]: any |}, ... - }, - >; + }, >; declare export var FormattedList: React$StatelessFunctionalComponent< IntlListFormatOptions & { value: React$Node[], ... - }, - >; + }, >; declare export class FormattedMessage< - V: { [key: string]: any, ... } = { + V: {| [key: string]: any |} = {| [key: string]: | PrimitiveType | React_2.ReactElement<> | FormatXMLElementFn, - ..., - }, + |}, // Changed `mixins` to `extends` in TS to Flow translation > extends React$Component> { static displayName: string; @@ -254,15 +246,13 @@ declare module 'react-intl' { CustomFormatConfig & { value: number, ... - }, - >; + }, >; declare export var FormattedNumberParts: React$StatelessFunctionalComponent< $PropertyType & { value: $ElementType>, 0>, children(val: Intl.NumberFormatPart[]): React_2.ReactElement<> | null, ... - }, - >; + }, >; declare export var FormattedPlural: React$StatelessFunctionalComponent> & { WrappedComponent: React$ComponentType, ... @@ -286,15 +276,13 @@ declare module 'react-intl' { CustomFormatConfig & { value: string | number | Date | void, ... - }, - >; + }, >; declare export var FormattedTimeParts: React$StatelessFunctionalComponent< FormatDateOptions & { value: $ElementType>, 0> | string, children(val: Intl.DateTimeFormatPart[]): React_2.ReactElement<> | null, ... - }, - >; + }, >; declare type Formatter = { formatDate: FormatDateOptions, formatTime: FormatDateOptions, @@ -341,32 +329,30 @@ declare module 'react-intl' { WrappedComponent: React$ComponentType

, options?: Opts, ): React_2.ForwardRefExoticComponent< - React_2.PropsWithoutRef>> & React_2.RefAttributes, - > & { + React_2.PropsWithoutRef>> & React_2.RefAttributes, > & { WrappedComponent: React$ComponentType

, ... }; declare export interface IntlCache { - dateTime: { [key: string]: Intl.DateTimeFormat, ... }; - number: { [key: string]: Intl.NumberFormat, ... }; - message: { [key: string]: IntlMessageFormat, ... }; - relativeTime: { [key: string]: RelativeTimeFormat, ... }; - pluralRules: { [key: string]: Intl.PluralRules, ... }; - list: { [key: string]: ListFormat, ... }; - displayNames: { [key: string]: DisplayNames, ... }; + dateTime: {| [key: string]: Intl.DateTimeFormat |}; + number: {| [key: string]: Intl.NumberFormat |}; + message: {| [key: string]: IntlMessageFormat |}; + relativeTime: {| [key: string]: RelativeTimeFormat |}; + pluralRules: {| [key: string]: Intl.PluralRules |}; + list: {| [key: string]: ListFormat |}; + displayNames: {| [key: string]: DisplayNames |}; } declare export interface IntlConfig { locale: string; timeZone?: string; formats: CustomFormats; textComponent?: React$ComponentType<> | $Keys; - messages: { [key: string]: string, ... } | { [key: string]: MessageFormatElement[], ... }; + messages: {| [key: string]: string |} | {| [key: string]: MessageFormatElement[] |}; defaultLocale: string; defaultFormats: CustomFormats; wrapRichTextChunksInFragment?: boolean; onError( - err: - | MissingTranslationError + err: | MissingTranslationError | MessageFormatError | MissingDataError | InvalidConfigError @@ -413,13 +399,13 @@ declare module 'react-intl' { descriptor: MessageDescriptor, // The `+` was added to make the properties covariant rather // than invariant, something TypeScript can't do. - values?: { +[key: string]: PrimitiveType | FormatXMLElementFn, ... }, + values?: {| +[key: string]: PrimitiveType | FormatXMLElementFn |}, ): string; formatMessage( descriptor: MessageDescriptor, // The `+` was added to make the properties covariant rather // than invariant, something TypeScript can't do. - values?: { +[key: string]: PrimitiveType | React$Node | FormatXMLElementFn, ... }, + values?: {| +[key: string]: PrimitiveType | React$Node | FormatXMLElementFn |}, ): React$Node; formatList(values: Array, opts?: FormatListOptions): string; formatList(values: Array, opts?: FormatListOptions): React$Node; @@ -463,9 +449,8 @@ declare module 'react-intl' { opts?: Options, ): this; format: ( - values?: { - [key: string]: - | string + values?: {| + [key: string]: | string | number | boolean | Date @@ -473,13 +458,11 @@ declare module 'react-intl' { | FormatXMLElementFn | null | void, - ..., - } | void, + |} | void, ) => string | T | (string | T)[]; formatToParts: ( - values?: { - [key: string]: - | string + values?: {| + [key: string]: | string | number | boolean | Date @@ -487,8 +470,7 @@ declare module 'react-intl' { | FormatXMLElementFn | null | void, - ..., - } | void, + |} | void, ) => MessageFormatPart[]; resolvedOptions: () => { locale: string, @@ -568,9 +550,11 @@ declare module 'react-intl' { ... }; } - declare export class IntlProvider + declare export class IntlProvider extends React$PureComponent< // Changed `mixins` to `extends` in TS to Flow translation - extends React$PureComponent, State> { + React_2.PropsWithChildren, + State, + > { static displayName: string; static defaultProps: Pick< IntlConfig, @@ -580,8 +564,7 @@ declare module 'react-intl' { | 'messages' | 'textComponent' | 'defaultLocale' - | 'defaultFormats', - >; + | 'defaultFormats', >; state: State; static getDerivedStateFromProps( props: OptionalIntlConfig, @@ -643,7 +626,7 @@ declare module 'react-intl' { options?: Pick, ): string[]; static __addLocaleData(...data: ListPatternLocaleData[]): void; - static localeData: { [key: string]: ListPatternFieldsData, ... }; + static localeData: {| [key: string]: ListPatternFieldsData |}; static polyfilled: boolean; } declare interface ListPattern { @@ -674,10 +657,12 @@ declare module 'react-intl' { } declare type Locale = string; declare interface LocaleData { - data: { [key: Locale]: T, ... }; + data: {| [key: Locale]: T |}; availableLocales: string[]; } - declare type LocaleFieldsData = $ObjMapi<{ [k: RelativeTimeField]: any }, (f) => FieldData> & { + declare type LocaleFieldsData = $ObjMapi< + {| [k: RelativeTimeField]: any |}, + (f) => FieldData, > & { nu?: Array, ... }; @@ -693,7 +678,7 @@ declare module 'react-intl' { // Changed from interface to type in TS to Flow translation declare export type MessageDescriptor = { id?: string | number, - description?: string | { [key: string]: any }, + description?: string | {| [key: string]: any |}, defaultMessage?: string, }; declare type MessageFormatElement = @@ -819,7 +804,7 @@ declare module 'react-intl' { +object: 1, // 1 |}; declare type PluralElement = { - options: { [key: ValidPluralRule]: PluralOrSelectOption, ... }, + options: {| [key: ValidPluralRule]: PluralOrSelectOption |}, offset: number, pluralType: $PropertyType, ... @@ -852,7 +837,7 @@ declare module 'react-intl' { children?: (value: React$Node) => React_2.ReactElement<> | null, ... } & FormatPluralOptions; - declare type Props_3 = { + declare type Props_3 = { values?: V, tagName?: React_2.ElementType, children?: (...nodes: React_2.ReactNodeArray) => React$Node, @@ -873,7 +858,7 @@ declare module 'react-intl' { +MISSING_TRANSLATION: 'MISSING_TRANSLATION', // "MISSING_TRANSLATION" |}; declare type RegionCode = string; - declare type RelativeTimeData = $ObjMapi<{ [k: LDMLPluralRule]: any }, (u) => string>; + declare type RelativeTimeData = $ObjMapi<{| [k: LDMLPluralRule]: any |}, (u) => string>; declare type RelativeTimeField = | 'second' | 'second-short' @@ -909,7 +894,7 @@ declare module 'react-intl' { options?: Pick, ): string[]; static __addLocaleData(...data: RelativeTimeLocaleData[]): void; - static localeData: { [key: string]: LocaleFieldsData, ... }; + static localeData: {| [key: string]: LocaleFieldsData |}; static polyfilled: boolean; } declare type RelativeTimeFormatNumberPart = { @@ -964,7 +949,7 @@ declare module 'react-intl' { }; declare type ScriptCode = string; declare type SelectElement = { - options: { [key: string]: PluralOrSelectOption, ... }, + options: {| [key: string]: PluralOrSelectOption |}, ... } & BaseElement; declare type SimpleFormatElement, S: Skeleton> = { @@ -1040,8 +1025,7 @@ declare module 'react-intl' { ... }; declare export type WrappedComponentProps = $ObjMapi< - { [k: IntlPropName]: any }, - (k) => IntlShape, - >; + {| [k: IntlPropName]: any |}, + (k) => IntlShape, >; declare export {}; } diff --git a/flow-typed/react-native-url-polyfill_vx.x.x.js b/flow-typed/react-native-url-polyfill_vx.x.x.js index 75bd7d22dbb..be250ce390d 100644 --- a/flow-typed/react-native-url-polyfill_vx.x.x.js +++ b/flow-typed/react-native-url-polyfill_vx.x.x.js @@ -28,7 +28,7 @@ declare module 'react-native-url-polyfill/js/URLSearchParams' { declare export class URLSearchParams { @@iterator(): Iterator<[string, string]>; constructor( - query?: string | URLSearchParams | Array<[string, string]> | { [string]: string }, + query?: string | URLSearchParams | Array<[string, string]> | {| [string]: string |}, ): void; append(name: string, value: string): void; delete(name: string): void; diff --git a/flow-typed/react-native-webview_v10.x.x.js b/flow-typed/react-native-webview_v10.x.x.js index 3bdafafc3a8..43f42813059 100644 --- a/flow-typed/react-native-webview_v10.x.x.js +++ b/flow-typed/react-native-webview_v10.x.x.js @@ -138,7 +138,7 @@ declare module 'react-native-webview' { declare export type WebViewSourceUri = {| uri?: string, method?: string, - headers?: { [string]: string }, + headers?: {| [string]: string |}, body?: string, |}; diff --git a/package.json b/package.json index 0cd97f207b5..fad5a8105b9 100644 --- a/package.json +++ b/package.json @@ -116,7 +116,7 @@ "eslint-plugin-prettier": "^3.2.0", "eslint-plugin-react": "^7.21.5", "eslint-plugin-react-hooks": "^4.2.0", - "flow-bin": "^0.122.0", + "flow-bin": "^0.128.0", "flow-coverage-report": "^0.6.0", "flow-typed": "^2.4.0", "immutable-devtools": "^0.1.5", diff --git a/src/__tests__/lib/exampleData.js b/src/__tests__/lib/exampleData.js index 7782ac1fa29..2b9c1384059 100644 --- a/src/__tests__/lib/exampleData.js +++ b/src/__tests__/lib/exampleData.js @@ -330,9 +330,9 @@ export const pmMessage = (args?: {| // The `Object.freeze` is to work around a Flow issue: // https://github.com/facebook/flow/issues/2386#issuecomment-695064325 const { - sender = otherUser, - recipients = [otherUser, selfUser], sender_id = undefined, + sender = sender_id != null ? makeUser({ user_id: sender_id }) : otherUser, + recipients = [otherUser, selfUser], ...extra } = args ?? Object.freeze({}); @@ -355,7 +355,6 @@ export const pmMessage = (args?: {| return deepFreeze({ ...baseMessage, - ...(sender_id != null && { sender_id: makeUserId(sender_id) }), ...extra, }); }; @@ -674,7 +673,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 diff --git a/src/api/initialDataTypes.js b/src/api/initialDataTypes.js index 62686e294c7..af32e0c9f34 100644 --- a/src/api/initialDataTypes.js +++ b/src/api/initialDataTypes.js @@ -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, diff --git a/src/api/modelTypes.js b/src/api/modelTypes.js index b3cd66efc65..3d14bddd8e3 100644 --- a/src/api/modelTypes.js +++ b/src/api/modelTypes.js @@ -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 diff --git a/src/autocomplete/PeopleAutocomplete.js b/src/autocomplete/PeopleAutocomplete.js index e5652db02a5..0e387d54992 100644 --- a/src/autocomplete/PeopleAutocomplete.js +++ b/src/autocomplete/PeopleAutocomplete.js @@ -87,16 +87,18 @@ class PeopleAutocomplete extends PureComponent { return ( - {/* - $FlowFixMe[incompatible-variance] - $FlowFixMe[prop-missing] - SectionList type is confused; should take $ReadOnly objects. - */} - + {/* eslint-disable-next-line react/jsx-curly-brace-presence */} + { + // $FlowFixMe[incompatible-variance] + /* $FlowFixMe[prop-missing] + SectionList type is confused; should take $ReadOnly + objects. */ + + } ); } diff --git a/src/boot/store.js b/src/boot/store.js index 55aaba8060e..c1f538d2941 100644 --- a/src/boot/store.js +++ b/src/boot/store.js @@ -90,8 +90,13 @@ export const cacheKeys: Array<$Keys> = [ function dropCache(state: GlobalState): $Shape { const result: $Shape = {}; storeKeys.forEach(key => { - /* $FlowFixMe[incompatible-type]: This is well-typed only because - it's the same `key` twice. */ + // $FlowFixMe[incompatible-indexer] + // $FlowFixMe[incompatible-exact] + // $FlowFixMe[prop-missing] + // $FlowFixMe[incompatible-variance] + // $FlowFixMe[incompatible-type-arg] + /* $FlowFixMe[incompatible-type] + This is well-typed only because it's the same `key` twice. */ result[key] = state[key]; }); return result; @@ -106,7 +111,7 @@ function dropCache(state: GlobalState): $Shape { * 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`. @@ -168,8 +173,8 @@ const migrations: { [string]: (GlobalState) => GlobalState } = { ...state, accounts: state.accounts.map(a => ({ ...a, - // `a.realm` is a string until migration 15 - // $FlowMigrationFudge[prop-missing] + /* $FlowIgnore[prop-missing]: `a.realm` is a string until + migration 15 */ realm: a.realm.replace(/\/+$/, ''), })), }), @@ -206,8 +211,8 @@ const migrations: { [string]: (GlobalState) => GlobalState } = { ...state, accounts: state.accounts.map(a => ({ ...a, - /* $FlowMigrationFudge[incompatible-call]: `a.realm` will be a - string here */ + /* $FlowIgnore[incompatible-call]: `a.realm` will be a string + here */ realm: new URL(a.realm), })), }), diff --git a/src/compose/ComposeMenu.js b/src/compose/ComposeMenu.js index 964129ec333..11a4119ec3a 100644 --- a/src/compose/ComposeMenu.js +++ b/src/compose/ComposeMenu.js @@ -83,7 +83,9 @@ class ComposeMenu extends PureComponent { return; } - // $FlowFixMe[sketchy-null-bool]: Upstream API is unclear. + // $FlowFixMe[sketchy-null-string] + /* $FlowFixMe[sketchy-null-bool] + Upstream API is unclear. */ const error: string | null = response.error || null; if (error !== null) { showErrorAlert('Error', error); diff --git a/src/directSelectors.js b/src/directSelectors.js index 16d720f288c..c1e39f13f35 100644 --- a/src/directSelectors.js +++ b/src/directSelectors.js @@ -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; diff --git a/src/emoji/codePointMap.js b/src/emoji/codePointMap.js index 622bdc6638c..9fae7e72bd3 100644 --- a/src/emoji/codePointMap.js +++ b/src/emoji/codePointMap.js @@ -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', diff --git a/src/emoji/data.js b/src/emoji/data.js index 4df6665383e..d5c0fb4c4c2 100644 --- a/src/emoji/data.js +++ b/src/emoji/data.js @@ -35,7 +35,7 @@ export const codeToEmojiMap = objectFromEntries( */ 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 diff --git a/src/emoji/emojiSelectors.js b/src/emoji/emojiSelectors.js index 06cedbcab92..341c39bcec9 100644 --- a/src/emoji/emojiSelectors.js +++ b/src/emoji/emojiSelectors.js @@ -10,7 +10,7 @@ export const getAllImageEmojiById: Selector = 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 = createSelector( export const getActiveImageEmojiById: Selector = 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 = 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]])), ); diff --git a/src/emoji/zulipExtraEmojiMap.js b/src/emoji/zulipExtraEmojiMap.js index 662bb8fb2a8..e387faf3025 100644 --- a/src/emoji/zulipExtraEmojiMap.js +++ b/src/emoji/zulipExtraEmojiMap.js @@ -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', diff --git a/src/jsBackport.js b/src/jsBackport.js index 36fa2140587..c7d87ad20dc 100644 --- a/src/jsBackport.js +++ b/src/jsBackport.js @@ -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 diff --git a/src/message/messageActionSheet.js b/src/message/messageActionSheet.js index 8df6f9f25b0..620cc7074c6 100644 --- a/src/message/messageActionSheet.js +++ b/src/message/messageActionSheet.js @@ -237,7 +237,7 @@ const allButtonsRaw = { type ButtonCode = $Keys; -const allButtons: { [ButtonCode]: ButtonDescription } = allButtonsRaw; +const allButtons: {| [ButtonCode]: ButtonDescription |} = allButtonsRaw; type ConstructSheetParams = {| backgroundData: BackgroundData, diff --git a/src/pm-conversations/pmConversationsSelectors.js b/src/pm-conversations/pmConversationsSelectors.js index d2c10c65021..f537a5fc3c1 100644 --- a/src/pm-conversations/pmConversationsSelectors.js +++ b/src/pm-conversations/pmConversationsSelectors.js @@ -38,8 +38,8 @@ export const getRecentConversationsLegacy: Selector = crea ( ownUserId, messages: Message[], - unreadPms: { [number]: number }, - unreadHuddles: { [string]: number }, + unreadPms: {| [number]: number |}, + unreadHuddles: {| [string]: number |}, allUsersById, ): PmConversationData[] => { const items = messages diff --git a/src/presence/presenceReducer.js b/src/presence/presenceReducer.js index a100d7f529b..7f03edadc3c 100644 --- a/src/presence/presenceReducer.js +++ b/src/presence/presenceReducer.js @@ -41,17 +41,17 @@ export default (state: PresenceState = initialState, action: Action): PresenceSt return { ...state, + // Flow bug (unresolved): + // https://github.com/facebook/flow/issues/8276 + // $FlowIssue #8276 [action.email]: { ...state[action.email], + ...action.presence, // Flow bug (unresolved): // https://github.com/facebook/flow/issues/8276 // $FlowIssue #8276 - ...action.presence, aggregated: getAggregatedPresence({ ...state[action.email], - // Flow bug (unresolved): - // https://github.com/facebook/flow/issues/8276 - // $FlowIssue #8276 ...action.presence, }), }, diff --git a/src/redux-persist-migrate/index.js b/src/redux-persist-migrate/index.js index 0bf56744fbe..25dcb183aed 100644 --- a/src/redux-persist-migrate/index.js +++ b/src/redux-persist-migrate/index.js @@ -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> { @@ -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> { @@ -75,8 +75,10 @@ export function createMigrationImpl( throw new Error('createMigration: bad arguments'); } if (action.type === REHYDRATE) { - /* $FlowMigrationFudge[incompatible-type]: this really is a lie - -- and kind of central to migration */ + // $FlowIgnore[prop-missing] + // $FlowIgnore[incompatible-exact] + /* $FlowIgnore[incompatible-type] + this really is a lie -- and kind of central to migration */ const incomingState: State = action.payload; const incomingVersion = parseInt(versionSelector(incomingState), 10); if (Number.isNaN(incomingVersion)) { diff --git a/src/reduxTypes.js b/src/reduxTypes.js index ad36c7e3944..92d8a79dd61 100644 --- a/src/reduxTypes.js +++ b/src/reduxTypes.js @@ -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; @@ -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[]; diff --git a/src/streams/StreamList.js b/src/streams/StreamList.js index 22fd88054d7..f38083152c3 100644 --- a/src/streams/StreamList.js +++ b/src/streams/StreamList.js @@ -21,7 +21,7 @@ type Props = $ReadOnly<{| showDescriptions: boolean, showSwitch: boolean, streams: $ReadOnlyArray, - unreadByStream: $ReadOnly<{ [number]: number }>, + unreadByStream: $ReadOnly<{| [number]: number |}>, onPress: (streamName: string) => void, onSwitch?: (streamName: string, newValue: boolean) => void, |}>; diff --git a/src/streams/SubscriptionsCard.js b/src/streams/SubscriptionsCard.js index 810b62c8de1..23daf1b50b8 100644 --- a/src/streams/SubscriptionsCard.js +++ b/src/streams/SubscriptionsCard.js @@ -24,7 +24,7 @@ const styles = createStyleSheet({ type SelectorProps = $ReadOnly<{| subscriptions: Subscription[], - unreadByStream: $ReadOnly<{ [number]: number }>, + unreadByStream: $ReadOnly<{| [number]: number |}>, |}>; type Props = $ReadOnly<{| diff --git a/src/styles/theme.js b/src/styles/theme.js index 261454b2512..68c4e3c1e1a 100644 --- a/src/styles/theme.js +++ b/src/styles/theme.js @@ -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%)', diff --git a/src/types.js b/src/types.js index 164cb8cc3d4..cb0636aec1b 100644 --- a/src/types.js +++ b/src/types.js @@ -236,7 +236,7 @@ export type MessageLike = | $ReadOnly | $ReadOnly<{ // $Shape is unsound, per Flow docs, but $ReadOnly<$Shape> is not - ...$Shape<{ [$Keys]: void }>, + ...$Shape<{| [$Keys]: 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, }; diff --git a/src/unread/UnreadCards.js b/src/unread/UnreadCards.js index 6be1fb055b4..f42d507a8e7 100644 --- a/src/unread/UnreadCards.js +++ b/src/unread/UnreadCards.js @@ -35,8 +35,9 @@ export default function UnreadCards(props: Props) { } return ( - /* $FlowFixMe[prop-missing]: SectionList libdef seems confused; - should take $ReadOnly objects. */ + // $FlowFixMe[incompatible-type-arg] + /* $FlowFixMe[prop-missing] + SectionList libdef seems confused; should take $ReadOnly objects. */ = 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 = 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 = 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; diff --git a/src/utils/jsonable.js b/src/utils/jsonable.js index 8676e3fc0b0..c21fda86e28 100644 --- a/src/utils/jsonable.js +++ b/src/utils/jsonable.js @@ -17,7 +17,7 @@ export type JSONable = | string | number | boolean - | { +[string]: JSONable } // [α] + | {| +[string]: JSONable |} // [α] | $ReadOnlyArray; // [α] This should just be `JSONableDict`, but Flow doesn't handle // mutually-recursive types very well. @@ -27,24 +27,7 @@ export type JSONable = * * See documentation of `JSONable` for caveats. */ -export type JSONableDict = { +[string]: JSONable }; -// This should really be an exact type, `{| +[string]: JSONable |}`. -// Unfortunately, it can't yet be. -// -// Prior to Flow v0.126.0, exact object types with indexer properties -// are unusably broken. The following trivial example fails to -// typecheck: -// -// const val: {| [string]: number |} = { foo: 3 }; -// -// On the other hand, inexact indexer-property types don't actually have their -// properties typechecked at their point of use -- that is, the following passes -// typechecking (even after v0.126.0): -// -// const val: { [string]: number } = { foo: 3, bar: 'baz' }; -// -// ... which is consistent with the definition of inexact types, if -// inconvenient. +export type JSONableDict = {| +[string]: JSONable |}; /** * Approximate type of a JSONable value received as input. @@ -54,7 +37,7 @@ export type JSONableDict = { +[string]: JSONable }; * by-design soundness hole involving indexer elements: * * ```flow - * const obj: { [string]: string } = { a: "a" }; + * const obj: {| [string]: string |} = { a: "a" }; * const value: string = obj['b']; * value.trim(); // kaboom! * ``` @@ -89,7 +72,7 @@ export type JSONableInput = | string | number | boolean - | { +[string]: JSONableInput | void } + | {| +[string]: JSONableInput | void |} | $ReadOnlyArray; /** @@ -97,4 +80,4 @@ export type JSONableInput = * * See documentation of `JSONable` and `JSONableInput` for caveats. */ -export type JSONableInputDict = { +[string]: JSONableInput | void }; +export type JSONableInputDict = {| +[string]: JSONableInput | void |}; diff --git a/src/utils/logging.js b/src/utils/logging.js index 93cf31e46c4..adc188681af 100644 --- a/src/utils/logging.js +++ b/src/utils/logging.js @@ -13,9 +13,7 @@ import objectEntries from './objectEntries'; import config from '../config'; /** Type of "extras" intended for Sentry. */ -// This type should be exact, but cannot be until Flow v0.126.0. (See note in -// `jsonable.js`.) -type Extras = { +[key: string]: JSONable }; +type Extras = {| +[key: string]: JSONable |}; /** Wrapper for `Sentry.withScope`, allowing callbacks to return values. */ function withScope(callback: Scope => R): R { diff --git a/src/utils/misc.js b/src/utils/misc.js index 6ecf7fac895..0d944b945e2 100644 --- a/src/utils/misc.js +++ b/src/utils/misc.js @@ -8,7 +8,7 @@ export const caseInsensitiveCompareFunc = (a: string, b: string): number => export const numberWithSeparators = (value: number | string): string => value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ','); -export function deeperMerge(obj1: { [K]: V }, obj2: { [K]: V }): { [K]: V } { +export function deeperMerge(obj1: {| [K]: V |}, obj2: {| [K]: V |}): {| [K]: V |} { const mergedKeys = Array.from(new Set([...Object.keys(obj1), ...Object.keys(obj2)])); return objectFromEntries( mergedKeys.map(key => diff --git a/src/utils/objectEntries.js b/src/utils/objectEntries.js index dbd2e0c9c0a..b8f815475e0 100644 --- a/src/utils/objectEntries.js +++ b/src/utils/objectEntries.js @@ -6,26 +6,8 @@ // static entries(object: mixed): Array<[string, mixed]>; // .... which is almost useless. -type EntriesType = ({ +[K]: V }) => $ReadOnlyArray<[K, V]>; +type EntriesType = ({| +[K]: V |}) => $ReadOnlyArray<[K, V]>; const objectEntries: EntriesType = obj => (Object.entries(obj): $FlowFixMe); export default objectEntries; - -/* - * Note that the above definition is formally unsound. In particular, - * - * ``` - * const obj: { 'foo': string } = { foo: "yes", bar: 2 }; - * const vals: string[] = entries(obj).map(s => s[1]); - * const valsPadded: string[] = vals.map(v => v.padStart(5)); - * ``` - * - * ... will pass typechecking, but fail at runtime. - * - * To make this function sound, it is necessary that the input type be an - * _exact_ type. However, the primary use case for this function is map-objects - * declared with indexer properties; and, until Flow v0.126.0, exact types with - * indexer properties are unusable. (See comments in ./jsonable.js for more - * information.) - */ diff --git a/src/utils/timing.js b/src/utils/timing.js index 0c1c9f44d80..293daa62946 100644 --- a/src/utils/timing.js +++ b/src/utils/timing.js @@ -1,7 +1,7 @@ /* @flow strict-local */ import type { TimingItemType } from '../types'; -const startMsMap: { [string]: number } = {}; +const startMsMap: {| [string]: number |} = {}; const log: TimingItemType[] = []; const add = (item: TimingItemType) => { diff --git a/src/utils/url.js b/src/utils/url.js index 9ef2f2f1606..a35ca08adcb 100644 --- a/src/utils/url.js +++ b/src/utils/url.js @@ -10,7 +10,7 @@ import objectEntries from './objectEntries'; * primitive types for which `toString` is just as good as `JSON.stringify`. */ export type UrlParamValue = string | boolean | number; -export type UrlParams = $ReadOnly<{ [string]: UrlParamValue | void }>; +export type UrlParams = $ReadOnly<{| [string]: UrlParamValue | void |}>; /** * Encode parameters as if for the URL query-part submitting an HTML form. @@ -108,7 +108,7 @@ const getResourceNoAuth = (uri: string) => ({ export const getResource = ( uri: string, auth: Auth, -): {| uri: string, headers?: { [string]: string } |} => +): {| uri: string, headers?: {| [string]: string |} |} => isUrlOnRealm(uri, auth.realm) ? getResourceWithAuth(uri, auth) : getResourceNoAuth(uri); export type Protocol = 'https://' | 'http://'; diff --git a/src/webview/MessageList.js b/src/webview/MessageList.js index e82ab291f32..e0655a65e12 100644 --- a/src/webview/MessageList.js +++ b/src/webview/MessageList.js @@ -72,7 +72,7 @@ import { tryParseUrl } from '../utils/url'; */ export type BackgroundData = $ReadOnly<{| alertWords: AlertWordsState, - allImageEmojiById: $ReadOnly<{ [id: string]: ImageEmojiType }>, + allImageEmojiById: $ReadOnly<{| [id: string]: ImageEmojiType |}>, auth: Auth, debug: Debug, flags: FlagsState, diff --git a/src/webview/html/messageAsHtml.js b/src/webview/html/messageAsHtml.js index 09de4c8299e..4df03408884 100644 --- a/src/webview/html/messageAsHtml.js +++ b/src/webview/html/messageAsHtml.js @@ -32,7 +32,7 @@ const messageTagsAsHtml = (isStarred: boolean, timeEdited: number | void): strin const messageReactionAsHtml = ( reaction: AggregatedReaction, - allImageEmojiById: $ReadOnly<{ [id: string]: ImageEmojiType }>, + allImageEmojiById: $ReadOnly<{| [id: string]: ImageEmojiType |}>, ): string => template`, ownUserId: UserId, - allImageEmojiById: $ReadOnly<{ [id: string]: ImageEmojiType }>, + allImageEmojiById: $ReadOnly<{| [id: string]: ImageEmojiType |}>, ): string => { if (reactions.length === 0) { return ''; diff --git a/src/webview/js/InboundEventLogger.js b/src/webview/js/InboundEventLogger.js index 41115735f40..8e4e8a74402 100644 --- a/src/webview/js/InboundEventLogger.js +++ b/src/webview/js/InboundEventLogger.js @@ -11,8 +11,7 @@ import type { JSONable } from '../../utils/jsonable'; import sendMessage from './sendMessage'; import { ensureUnreachable } from '../../types'; -// TODO: Make exact (see note in jsonable.js). -type Scrub = { [key: $Keys]: JSONable }; +type Scrub = {| [key: $Keys]: JSONable |}; type ScrubbedInboundEvent = | Scrub diff --git a/src/webview/js/js.js b/src/webview/js/js.js index 63c3f4ddd63..3e4734d65c7 100644 --- a/src/webview/js/js.js +++ b/src/webview/js/js.js @@ -53,10 +53,9 @@ declare var platformOS: string; /* Polyfill Array.from. Native in Chrome 45 and at least Safari 13. Leaves out some of the fancy features (see MDN). */ -type ArrayLike = { [indexer: number]: T, length: number, ... }; if (!Array.from) { // $FlowFixMe[cannot-write] (polyfill) - Array.from = function from(arr: ArrayLike): Array { + Array.from = function from(arr: $ArrayLike): Array { return Array.prototype.slice.call(arr); }; } @@ -675,6 +674,7 @@ const handleMessageEvent: MessageEventListener = e => { inboundEvents.forEach((uevent: WebViewInboundEvent) => { eventLogger.maybeCaptureInboundEvent(uevent); + // $FlowFixMe[incompatible-type] // $FlowFixMe[prop-missing] inboundEventHandlers[uevent.type](uevent); }); diff --git a/yarn.lock b/yarn.lock index 30964768a50..3b57add3513 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5621,10 +5621,10 @@ flow-annotation-check@1.8.1: glob "7.1.1" load-pkg "^3.0.1" -flow-bin@^0.122.0: - version "0.122.0" - resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.122.0.tgz#c723a2b33b1a70bd10204704ae1dc776d5d89d79" - integrity sha512-my8N5jgl/A+UVby9E7NDppHdhLgRbWgKbmFZSx2MSYMRh3d9YGnM2MM+wexpUpl0ftY1IM6ZcUwaAhrypLyvlA== +flow-bin@^0.128.0: + version "0.128.0" + resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.128.0.tgz#fd1232a64dc46874d8d499f16a1934b964f4c2ae" + integrity sha512-EnmMSOCrkx8F0r1+T1d1HODQ+ddy5yRfkT3CvwmK05IWZyXQy27OVdNwdXUWRqc0iMW75T4QkoXaVBYrMqfk+A== flow-coverage-report@^0.6.0: version "0.6.2"