From 3ff28f9febb9b64abc1c6b5bd68c806dc81f019e Mon Sep 17 00:00:00 2001 From: Marco Wang Date: Thu, 18 Dec 2025 11:52:32 -0800 Subject: [PATCH] Transform all Flow legacy utility types (`$Keys`) to TypeScript-style types in xplat/js Summary: We are transforming the following utility types to be more consistent with typescript and better AI integration: * `$NonMaybeType` -> `NonNullable` * `$ReadOnly` -> `Readonly` * `$ReadOnlyArray` -> `ReadonlyArray` * `$ReadOnlyMap` -> `ReadonlyMap` * `$ReadOnlySet` -> `ReadonlySet` * `$Keys` -> `keyof` * `$Values` -> `Values` * `mixed` -> `unknown` See details in https://fb.workplace.com/groups/flowlang/permalink/1837907750148213/. drop-conflicts Reviewed By: SamChou19815 Differential Revision: D89486050 --- flow-typed/npm/babel-traverse_v7.x.x.js | 10 +- flow-typed/npm/rxjs_v6.x.x.js | 4 +- .../src/inspector-proxy/Device.js | 48 +- .../src/inspector-proxy/cdp-types/messages.js | 6 +- .../Animated/createAnimatedComponent.js | 4 +- .../Libraries/AppState/AppState.js | 2 +- .../AccessibilityInfo/AccessibilityInfo.js | 497 +++++++++--------- .../Libraries/Components/Keyboard/Keyboard.js | 10 +- .../ProgressBarAndroid/ProgressBarAndroid.js | 2 +- .../Components/StatusBar/StatusBar.js | 18 +- .../EventEmitter/NativeEventEmitter.js | 10 +- .../EventEmitter/RCTDeviceEventEmitter.js | 2 +- .../__mocks__/NativeEventEmitter.js | 10 +- .../react-native/Libraries/Linking/Linking.js | 2 +- .../Network/RCTNetworking.android.js | 19 +- .../Libraries/Network/RCTNetworking.ios.js | 25 +- .../Libraries/Network/RCTNetworking.js.flow | 2 +- .../PushNotificationIOS.js | 4 +- .../ReactNative/RendererImplementation.js | 12 +- .../Libraries/StyleSheet/StyleSheet.js | 2 +- .../Libraries/StyleSheet/StyleSheet.js.flow | 2 +- .../StyleSheet/private/_TransformStyle.js | 4 +- .../Libraries/Types/ReactDevToolsTypes.js | 4 +- .../Utilities/codegenNativeCommands.js | 4 +- .../Libraries/vendor/emitter/EventEmitter.js | 22 +- .../private/__tests__/MemoryBaseline-itest.js | 10 +- .../utilities/accessibilityPropsSuite.js | 8 +- .../ReactNativeFeatureFlagsBase.js | 4 +- .../js/utils/RNTesterNavigationReducer.js | 26 +- .../Lists/StateSafePureComponent.js | 2 +- scripts/build/config.js | 6 +- 31 files changed, 376 insertions(+), 405 deletions(-) diff --git a/flow-typed/npm/babel-traverse_v7.x.x.js b/flow-typed/npm/babel-traverse_v7.x.x.js index 1cd8df07b182..67b4d9ba9b5d 100644 --- a/flow-typed/npm/babel-traverse_v7.x.x.js +++ b/flow-typed/npm/babel-traverse_v7.x.x.js @@ -558,24 +558,24 @@ declare module '@babel/traverse' { * Check whether we have the input `key`. If the `key` references an array then we check * if the array has any items, otherwise we just check if it's falsy. */ - has(key: $Keys): boolean; + has(key: keyof TNode): boolean; isStatic(): boolean; /** * Alias of `has`. */ - is(key: $Keys): boolean; + is(key: keyof TNode): boolean; /** * Opposite of `has`. */ - isnt(key: $Keys): boolean; + isnt(key: keyof TNode): boolean; /** * Check whether the path node `key` strict equals `value`. */ - equals(key: $Keys, value: any): boolean; + equals(key: keyof TNode, value: any): boolean; /** * Check the type against our stored internal type of the node. This is handy when a node has @@ -726,7 +726,7 @@ declare module '@babel/traverse' { getAllPrevSiblings(): Array>; - get>( + get( key: TKey, context?: boolean | TraversalContext, ): TNode[TKey] extends BabelNode ? NodePath<> : Array>; diff --git a/flow-typed/npm/rxjs_v6.x.x.js b/flow-typed/npm/rxjs_v6.x.x.js index 8963f46bf1fd..ebd8bbbcdea0 100644 --- a/flow-typed/npm/rxjs_v6.x.x.js +++ b/flow-typed/npm/rxjs_v6.x.x.js @@ -2186,10 +2186,10 @@ declare module 'rxjs/operators' { ): rxjs$MonoTypeOperatorFunction; declare export function distinctUntilKeyChanged( - key: $Keys, + key: keyof T, ): rxjs$MonoTypeOperatorFunction; - declare export function distinctUntilKeyChanged>( + declare export function distinctUntilKeyChanged( key: K, compare: (x: mixed, y: mixed) => boolean, ): rxjs$MonoTypeOperatorFunction; diff --git a/packages/dev-middleware/src/inspector-proxy/Device.js b/packages/dev-middleware/src/inspector-proxy/Device.js index 20d6ede32fc2..1035cd82e1af 100644 --- a/packages/dev-middleware/src/inspector-proxy/Device.js +++ b/packages/dev-middleware/src/inspector-proxy/Device.js @@ -36,18 +36,18 @@ const debug = require('debug')('Metro:InspectorProxy'); const PAGES_POLLING_INTERVAL = 1000; const WS_CLOSURE_CODE = { - NORMAL: 1000, INTERNAL_ERROR: 1011, + NORMAL: 1000, }; // should be aligned with // https://github.com/facebook/react-native-devtools-frontend/blob/3d17e0fd462dc698db34586697cce2371b25e0d3/front_end/ui/legacy/components/utils/TargetDetachedDialog.ts#L50-L64 export const WS_CLOSE_REASON = { - PAGE_NOT_FOUND: '[PAGE_NOT_FOUND] Debugger page not found', CONNECTION_LOST: '[CONNECTION_LOST] Connection lost to corresponding device', - RECREATING_DEVICE: '[RECREATING_DEVICE] Recreating device connection', NEW_DEBUGGER_OPENED: '[NEW_DEBUGGER_OPENED] New debugger opened for the same app instance', + PAGE_NOT_FOUND: '[PAGE_NOT_FOUND] Debugger page not found', + RECREATING_DEVICE: '[RECREATING_DEVICE] Recreating device connection', }; // Prefix for script URLs that are alphanumeric IDs. See comment in #processMessageFromDeviceLegacy method for @@ -160,9 +160,9 @@ export default class Device { this.#deviceRelativeBaseUrl = deviceRelativeBaseUrl; this.#deviceEventReporter = eventReporter ? new DeviceEventReporter(eventReporter, { + appId: app, deviceId: id, deviceName: name, - appId: app, }) : null; this.#createCustomMessageHandler = createMessageMiddleware; @@ -334,17 +334,17 @@ export default class Device { ); this.#deviceEventReporter?.logConnection('debugger', { - pageId, frontendUserAgent: userAgent, + pageId, }); const debuggerInfo: ?DebuggerConnection & DebuggerConnection = { - socket, - prependedFilePrefix: false, - pageId, - userAgent: userAgent, customHandler: null, debuggerRelativeBaseUrl, + pageId, + prependedFilePrefix: false, + socket, + userAgent, }; this.#debuggerConnection = debuggerInfo; @@ -357,9 +357,7 @@ export default class Device { if (this.#debuggerConnection && this.#createCustomMessageHandler) { this.#debuggerConnection.customHandler = this.#createCustomMessageHandler( { - page, debugger: { - userAgent: debuggerInfo.userAgent, sendMessage: message => { try { const payload = JSON.stringify(message); @@ -367,6 +365,7 @@ export default class Device { socket.send(payload); } catch {} }, + userAgent: debuggerInfo.userAgent, }, device: { appId: this.#app, @@ -386,6 +385,7 @@ export default class Device { } catch {} }, }, + page, }, ); @@ -405,8 +405,8 @@ export default class Device { this.#cdpDebugLogging.log('DebuggerToProxy', message); const debuggerRequest = JSON.parse(message); this.#deviceEventReporter?.logRequest(debuggerRequest, 'debugger', { - pageId: this.#debuggerConnection?.pageId ?? null, frontendUserAgent: userAgent, + pageId: this.#debuggerConnection?.pageId ?? null, prefersFuseboxFrontend: this.#isPageFuseboxFrontend( this.#debuggerConnection?.pageId, ), @@ -482,7 +482,7 @@ export default class Device { /** * Returns `true` if a page supports the given target capability flag. */ - #pageHasCapability(page: Page, flag: $Keys): boolean { + #pageHasCapability(page: Page, flag: keyof TargetCapabilityFlags): boolean { return page.capabilities[flag] === true; } @@ -491,11 +491,11 @@ export default class Device { */ #createSyntheticPage(): Page { return { + app: this.#app, + capabilities: {}, id: REACT_NATIVE_RELOADABLE_PAGE_ID, title: 'React Native Experimental (Improved Chrome Reloads)', vm: "don't use", - app: this.#app, - capabilities: {}, }; } @@ -596,8 +596,8 @@ export default class Device { const pageId = this.#debuggerConnection?.pageId ?? null; if ('id' in parsedPayload) { this.#deviceEventReporter?.logResponse(parsedPayload, 'device', { - pageId, frontendUserAgent: this.#debuggerConnection?.userAgent ?? null, + pageId, prefersFuseboxFrontend: this.#isPageFuseboxFrontend(pageId), }); } @@ -665,15 +665,15 @@ export default class Device { this.#sendConnectEventToDevice(page.id); const toSend = [ - {method: 'Runtime.enable', id: 1e9}, - {method: 'Debugger.enable', id: 1e9}, + {id: 1e9, method: 'Runtime.enable'}, + {id: 1e9, method: 'Debugger.enable'}, ]; for (const message of toSend) { const pageId = this.#debuggerConnection?.pageId ?? null; this.#deviceEventReporter?.logRequest(message, 'proxy', { - pageId, frontendUserAgent: this.#debuggerConnection?.userAgent ?? null, + pageId, prefersFuseboxFrontend: this.#isPageFuseboxFrontend(pageId), }); this.#sendMessageToDevice({ @@ -820,10 +820,10 @@ export default class Device { // // This is not an issue in VSCode/Nuclide where the IDE knows to resume // at its convenience. - const resumeMessage = {method: 'Debugger.resume', id: 0}; + const resumeMessage = {id: 0, method: 'Debugger.resume'}; this.#deviceEventReporter?.logRequest(resumeMessage, 'proxy', { - pageId: this.#debuggerConnection?.pageId ?? null, frontendUserAgent: this.#debuggerConnection?.userAgent ?? null, + pageId: this.#debuggerConnection?.pageId ?? null, prefersFuseboxFrontend: this.#isPageFuseboxFrontend( this.#debuggerConnection?.pageId, ), @@ -894,8 +894,8 @@ export default class Device { socket.send(JSON.stringify(response)); const pageId = this.#debuggerConnection?.pageId ?? null; this.#deviceEventReporter?.logResponse(response, 'proxy', { - pageId, frontendUserAgent: this.#debuggerConnection?.userAgent ?? null, + pageId, prefersFuseboxFrontend: this.#isPageFuseboxFrontend(pageId), }); return null; @@ -973,8 +973,8 @@ export default class Device { socket.send(JSON.stringify(response)); const pageId = this.#debuggerConnection?.pageId ?? null; this.#deviceEventReporter?.logResponse(response, 'proxy', { - pageId, frontendUserAgent: this.#debuggerConnection?.userAgent ?? null, + pageId, prefersFuseboxFrontend: this.#isPageFuseboxFrontend(pageId), }); }; @@ -988,8 +988,8 @@ export default class Device { this.#sendErrorToDebugger(error); const pageId = this.#debuggerConnection?.pageId ?? null; this.#deviceEventReporter?.logResponse(response, 'proxy', { - pageId, frontendUserAgent: this.#debuggerConnection?.userAgent ?? null, + pageId, prefersFuseboxFrontend: this.#isPageFuseboxFrontend(pageId), }); }; diff --git a/packages/dev-middleware/src/inspector-proxy/cdp-types/messages.js b/packages/dev-middleware/src/inspector-proxy/cdp-types/messages.js index b06c447b3b37..e2c0e2d3fa6d 100644 --- a/packages/dev-middleware/src/inspector-proxy/cdp-types/messages.js +++ b/packages/dev-middleware/src/inspector-proxy/cdp-types/messages.js @@ -12,18 +12,18 @@ import type {JSONSerializable} from '../types'; import type {Commands, Events} from './protocol'; // Note: A CDP event is a JSON-RPC notification with no `id` member. -export type CDPEvent = 'unknown'> = { +export type CDPEvent = { method: TEvent, params: Events[TEvent], }; -export type CDPRequest = 'unknown'> = { +export type CDPRequest = { method: TCommand, params: Commands[TCommand]['paramsType'], id: number, }; -export type CDPResponse = 'unknown'> = +export type CDPResponse = | { result: Commands[TCommand]['resultType'], id: number, diff --git a/packages/react-native/Libraries/Animated/createAnimatedComponent.js b/packages/react-native/Libraries/Animated/createAnimatedComponent.js index 3238bbd862b6..a730a2a0525e 100644 --- a/packages/react-native/Libraries/Animated/createAnimatedComponent.js +++ b/packages/react-native/Libraries/Animated/createAnimatedComponent.js @@ -65,9 +65,9 @@ type PassThroughProps = $ReadOnly<{ passthroughAnimatedPropExplicitValues?: ViewProps | null, }>; -type LooseOmit> = Pick< +type LooseOmit = Pick< O, - Exclude<$Keys, K>, + Exclude, >; export type AnimatedProps = LooseOmit< diff --git a/packages/react-native/Libraries/AppState/AppState.js b/packages/react-native/Libraries/AppState/AppState.js index 7c018733ff7e..b1456ec048e2 100644 --- a/packages/react-native/Libraries/AppState/AppState.js +++ b/packages/react-native/Libraries/AppState/AppState.js @@ -42,7 +42,7 @@ type AppStateEventDefinitions = { focus: [], }; -export type AppStateEvent = $Keys; +export type AppStateEvent = keyof AppStateEventDefinitions; type NativeAppStateEventDefinitions = { appStateDidChange: [{app_state: AppStateStatus}], diff --git a/packages/react-native/Libraries/Components/AccessibilityInfo/AccessibilityInfo.js b/packages/react-native/Libraries/Components/AccessibilityInfo/AccessibilityInfo.js index 69473b4f767f..3b75a9baa7c8 100644 --- a/packages/react-native/Libraries/Components/AccessibilityInfo/AccessibilityInfo.js +++ b/packages/react-native/Libraries/Components/AccessibilityInfo/AccessibilityInfo.js @@ -45,30 +45,28 @@ type AccessibilityEventDefinitions = { type AccessibilityEventTypes = 'click' | 'focus' | 'viewHoverEnter'; // Mapping of public event names to platform-specific event names. -const EventNames: Map< - $Keys, - string, -> = Platform.OS === 'android' - ? new Map([ - ['change', 'touchExplorationDidChange'], - ['reduceMotionChanged', 'reduceMotionDidChange'], - ['highTextContrastChanged', 'highTextContrastDidChange'], - ['screenReaderChanged', 'touchExplorationDidChange'], - ['accessibilityServiceChanged', 'accessibilityServiceDidChange'], - ['invertColorsChanged', 'invertColorDidChange'], - ['grayscaleChanged', 'grayscaleModeDidChange'], - ]) - : new Map([ - ['announcementFinished', 'announcementFinished'], - ['boldTextChanged', 'boldTextChanged'], - ['change', 'screenReaderChanged'], - ['grayscaleChanged', 'grayscaleChanged'], - ['invertColorsChanged', 'invertColorsChanged'], - ['reduceMotionChanged', 'reduceMotionChanged'], - ['reduceTransparencyChanged', 'reduceTransparencyChanged'], - ['screenReaderChanged', 'screenReaderChanged'], - ['darkerSystemColorsChanged', 'darkerSystemColorsChanged'], - ]); +const EventNames: Map = + Platform.OS === 'android' + ? new Map([ + ['change', 'touchExplorationDidChange'], + ['reduceMotionChanged', 'reduceMotionDidChange'], + ['highTextContrastChanged', 'highTextContrastDidChange'], + ['screenReaderChanged', 'touchExplorationDidChange'], + ['accessibilityServiceChanged', 'accessibilityServiceDidChange'], + ['invertColorsChanged', 'invertColorDidChange'], + ['grayscaleChanged', 'grayscaleModeDidChange'], + ]) + : new Map([ + ['announcementFinished', 'announcementFinished'], + ['boldTextChanged', 'boldTextChanged'], + ['change', 'screenReaderChanged'], + ['grayscaleChanged', 'grayscaleChanged'], + ['invertColorsChanged', 'invertColorsChanged'], + ['reduceMotionChanged', 'reduceMotionChanged'], + ['reduceTransparencyChanged', 'reduceTransparencyChanged'], + ['screenReaderChanged', 'screenReaderChanged'], + ['darkerSystemColorsChanged', 'darkerSystemColorsChanged'], + ]); /** * Sometimes it's useful to know whether or not the device has a screen reader @@ -80,6 +78,155 @@ const EventNames: Map< * See https://reactnative.dev/docs/accessibilityinfo */ const AccessibilityInfo = { + /** + * Add an event handler. Supported events: + * + * - `reduceMotionChanged`: Fires when the state of the reduce motion toggle changes. + * The argument to the event handler is a boolean. The boolean is `true` when a reduce + * motion is enabled (or when "Transition Animation Scale" in "Developer options" is + * "Animation off") and `false` otherwise. + * - `screenReaderChanged`: Fires when the state of the screen reader changes. The argument + * to the event handler is a boolean. The boolean is `true` when a screen + * reader is enabled and `false` otherwise. + * + * These events are only supported on iOS: + * + * - `boldTextChanged`: iOS-only event. Fires when the state of the bold text toggle changes. + * The argument to the event handler is a boolean. The boolean is `true` when a bold text + * is enabled and `false` otherwise. + * - `grayscaleChanged`: iOS-only event. Fires when the state of the gray scale toggle changes. + * The argument to the event handler is a boolean. The boolean is `true` when a gray scale + * is enabled and `false` otherwise. + * - `invertColorsChanged`: iOS-only event. Fires when the state of the invert colors toggle + * changes. The argument to the event handler is a boolean. The boolean is `true` when a invert + * colors is enabled and `false` otherwise. + * - `reduceTransparencyChanged`: iOS-only event. Fires when the state of the reduce transparency + * toggle changes. The argument to the event handler is a boolean. The boolean is `true` + * when a reduce transparency is enabled and `false` otherwise. + * - `announcementFinished`: iOS-only event. Fires when the screen reader has + * finished making an announcement. The argument to the event handler is a + * dictionary with these keys: + * - `announcement`: The string announced by the screen reader. + * - `success`: A boolean indicating whether the announcement was + * successfully made. + * - `darkerSystemColorsChanged`: iOS-only event. Fires when the state of the dark system colors + * toggle changes. The argument to the event handler is a boolean. The boolean is `true` when + * dark system colors is enabled and `false` otherwise. + * + * These events are only supported on Android: + * + * - `highTextContrastChanged`: Android-only event. Fires when the state of the high text contrast + * toggle changes. The argument to the event handler is a boolean. The boolean is `true` when + * high text contrast is enabled and `false` otherwise. + * + * See https://reactnative.dev/docs/accessibilityinfo#addeventlistener + */ + addEventListener( + eventName: K, + // $FlowFixMe[incompatible-type] - Flow bug with unions and generics (T128099423) + handler: (...AccessibilityEventDefinitions[K]) => void, + ): EventSubscription { + const deviceEventName = EventNames.get(eventName); + return deviceEventName == null + ? {remove(): void {}} + : // $FlowFixMe[incompatible-type] + RCTDeviceEventEmitter.addListener(deviceEventName, handler); + }, + /** + * Post a string to be announced by the screen reader. + * + * See https://reactnative.dev/docs/accessibilityinfo#announceforaccessibility + */ + announceForAccessibility(announcement: string): void { + if (Platform.OS === 'android') { + NativeAccessibilityInfoAndroid?.announceForAccessibility(announcement); + } else { + NativeAccessibilityManagerIOS?.announceForAccessibility(announcement); + } + }, + /** + * Post a string to be announced by the screen reader. + * - `announcement`: The string announced by the screen reader. + * - `options`: An object that configures the reading options. + * - `queue`: The announcement will be queued behind existing announcements. iOS only. + * - `priority`: The priority of the announcement. Possible values: 'low' | 'default' | 'high'. + * High priority announcements will interrupt any ongoing speech and cannot be interrupted. + * Default priority announcements will interrupt any ongoing speech but can be interrupted. + * Low priority announcements will not interrupt ongoing speech and can be interrupted. + * (iOS only). + */ + announceForAccessibilityWithOptions( + announcement: string, + options: {queue?: boolean, priority?: 'low' | 'default' | 'high'}, + ): void { + if (Platform.OS === 'android') { + NativeAccessibilityInfoAndroid?.announceForAccessibility(announcement); + } else { + if (NativeAccessibilityManagerIOS?.announceForAccessibilityWithOptions) { + NativeAccessibilityManagerIOS?.announceForAccessibilityWithOptions( + announcement, + options, + ); + } else { + NativeAccessibilityManagerIOS?.announceForAccessibility(announcement); + } + } + }, + /** + * Get the recommended timeout for changes to the UI needed by this user. + * + * See https://reactnative.dev/docs/accessibilityinfo#getrecommendedtimeoutmillis + */ + getRecommendedTimeoutMillis(originalTimeout: number): Promise { + if (Platform.OS === 'android') { + return new Promise((resolve, reject) => { + if (NativeAccessibilityInfoAndroid?.getRecommendedTimeoutMillis) { + NativeAccessibilityInfoAndroid.getRecommendedTimeoutMillis( + originalTimeout, + resolve, + ); + } else { + resolve(originalTimeout); + } + }); + } else { + return Promise.resolve(originalTimeout); + } + }, + /** + * Query whether Accessibility Service is currently enabled. + * + * Returns a promise which resolves to a boolean. + * The result is `true` when any service is enabled and `false` otherwise. + * + * @platform android + * + * See https://reactnative.dev/docs/accessibilityinfo/#isaccessibilityserviceenabled-android + */ + isAccessibilityServiceEnabled(): Promise { + return new Promise((resolve, reject) => { + if (Platform.OS === 'android') { + if ( + NativeAccessibilityInfoAndroid != null && + NativeAccessibilityInfoAndroid.isAccessibilityServiceEnabled != null + ) { + NativeAccessibilityInfoAndroid.isAccessibilityServiceEnabled(resolve); + } else { + reject( + new Error( + 'NativeAccessibilityInfoAndroid.isAccessibilityServiceEnabled is not available', + ), + ); + } + } else { + reject( + new Error( + 'isAccessibilityServiceEnabled is only available on Android', + ), + ); + } + }); + }, /** * Query whether bold text is currently enabled. * @@ -104,7 +251,35 @@ const AccessibilityInfo = { }); } }, - + /** + * Query whether dark system colors is currently enabled. iOS only. + * + * Returns a promise which resolves to a boolean. + * The result is `true` when dark system colors is enabled and `false` otherwise. + */ + isDarkerSystemColorsEnabled(): Promise { + return new Promise((resolve, reject) => { + if (Platform.OS === 'android') { + return Promise.resolve(false); + } else { + if ( + NativeAccessibilityManagerIOS?.getCurrentDarkerSystemColorsState != + null + ) { + NativeAccessibilityManagerIOS.getCurrentDarkerSystemColorsState( + resolve, + reject, + ); + } else { + reject( + new Error( + 'NativeAccessibilityManagerIOS.getCurrentDarkerSystemColorsState is not available', + ), + ); + } + } + }); + }, /** * Query whether grayscale is currently enabled. * @@ -139,7 +314,29 @@ const AccessibilityInfo = { }); } }, - + /** + * Query whether high text contrast is currently enabled. Android only. + * + * Returns a promise which resolves to a boolean. + * The result is `true` when high text contrast is enabled and `false` otherwise. + */ + isHighTextContrastEnabled(): Promise { + return new Promise((resolve, reject) => { + if (Platform.OS === 'android') { + if (NativeAccessibilityInfoAndroid?.isHighTextContrastEnabled != null) { + NativeAccessibilityInfoAndroid.isHighTextContrastEnabled(resolve); + } else { + reject( + new Error( + 'NativeAccessibilityInfoAndroid.isHighTextContrastEnabled is not available', + ), + ); + } + } else { + return Promise.resolve(false); + } + }); + }, /** * Query whether inverted colors are currently enabled. * @@ -174,7 +371,6 @@ const AccessibilityInfo = { }); } }, - /** * Query whether reduced motion is currently enabled. * @@ -203,93 +399,6 @@ const AccessibilityInfo = { } }); }, - - /** - * Query whether high text contrast is currently enabled. Android only. - * - * Returns a promise which resolves to a boolean. - * The result is `true` when high text contrast is enabled and `false` otherwise. - */ - isHighTextContrastEnabled(): Promise { - return new Promise((resolve, reject) => { - if (Platform.OS === 'android') { - if (NativeAccessibilityInfoAndroid?.isHighTextContrastEnabled != null) { - NativeAccessibilityInfoAndroid.isHighTextContrastEnabled(resolve); - } else { - reject( - new Error( - 'NativeAccessibilityInfoAndroid.isHighTextContrastEnabled is not available', - ), - ); - } - } else { - return Promise.resolve(false); - } - }); - }, - - /** - * Query whether dark system colors is currently enabled. iOS only. - * - * Returns a promise which resolves to a boolean. - * The result is `true` when dark system colors is enabled and `false` otherwise. - */ - isDarkerSystemColorsEnabled(): Promise { - return new Promise((resolve, reject) => { - if (Platform.OS === 'android') { - return Promise.resolve(false); - } else { - if ( - NativeAccessibilityManagerIOS?.getCurrentDarkerSystemColorsState != - null - ) { - NativeAccessibilityManagerIOS.getCurrentDarkerSystemColorsState( - resolve, - reject, - ); - } else { - reject( - new Error( - 'NativeAccessibilityManagerIOS.getCurrentDarkerSystemColorsState is not available', - ), - ); - } - } - }); - }, - - /** - * Query whether reduce motion and prefer cross-fade transitions settings are currently enabled. - * - * Returns a promise which resolves to a boolean. - * The result is `true` when prefer cross-fade transitions is enabled and `false` otherwise. - * - * See https://reactnative.dev/docs/accessibilityinfo#prefersCrossFadeTransitions - */ - prefersCrossFadeTransitions(): Promise { - return new Promise((resolve, reject) => { - if (Platform.OS === 'android') { - return Promise.resolve(false); - } else { - if ( - NativeAccessibilityManagerIOS?.getCurrentPrefersCrossFadeTransitionsState != - null - ) { - NativeAccessibilityManagerIOS.getCurrentPrefersCrossFadeTransitionsState( - resolve, - reject, - ); - } else { - reject( - new Error( - 'NativeAccessibilityManagerIOS.getCurrentPrefersCrossFadeTransitionsState is not available', - ), - ); - } - } - }); - }, - /** * Query whether reduced transparency is currently enabled. * @@ -314,7 +423,6 @@ const AccessibilityInfo = { }); } }, - /** * Query whether a screen reader is currently enabled. * @@ -343,106 +451,37 @@ const AccessibilityInfo = { } }); }, - /** - * Query whether Accessibility Service is currently enabled. + * Query whether reduce motion and prefer cross-fade transitions settings are currently enabled. * * Returns a promise which resolves to a boolean. - * The result is `true` when any service is enabled and `false` otherwise. - * - * @platform android + * The result is `true` when prefer cross-fade transitions is enabled and `false` otherwise. * - * See https://reactnative.dev/docs/accessibilityinfo/#isaccessibilityserviceenabled-android + * See https://reactnative.dev/docs/accessibilityinfo#prefersCrossFadeTransitions */ - isAccessibilityServiceEnabled(): Promise { + prefersCrossFadeTransitions(): Promise { return new Promise((resolve, reject) => { if (Platform.OS === 'android') { + return Promise.resolve(false); + } else { if ( - NativeAccessibilityInfoAndroid != null && - NativeAccessibilityInfoAndroid.isAccessibilityServiceEnabled != null + NativeAccessibilityManagerIOS?.getCurrentPrefersCrossFadeTransitionsState != + null ) { - NativeAccessibilityInfoAndroid.isAccessibilityServiceEnabled(resolve); + NativeAccessibilityManagerIOS.getCurrentPrefersCrossFadeTransitionsState( + resolve, + reject, + ); } else { reject( new Error( - 'NativeAccessibilityInfoAndroid.isAccessibilityServiceEnabled is not available', + 'NativeAccessibilityManagerIOS.getCurrentPrefersCrossFadeTransitionsState is not available', ), ); } - } else { - reject( - new Error( - 'isAccessibilityServiceEnabled is only available on Android', - ), - ); } }); }, - - /** - * Add an event handler. Supported events: - * - * - `reduceMotionChanged`: Fires when the state of the reduce motion toggle changes. - * The argument to the event handler is a boolean. The boolean is `true` when a reduce - * motion is enabled (or when "Transition Animation Scale" in "Developer options" is - * "Animation off") and `false` otherwise. - * - `screenReaderChanged`: Fires when the state of the screen reader changes. The argument - * to the event handler is a boolean. The boolean is `true` when a screen - * reader is enabled and `false` otherwise. - * - * These events are only supported on iOS: - * - * - `boldTextChanged`: iOS-only event. Fires when the state of the bold text toggle changes. - * The argument to the event handler is a boolean. The boolean is `true` when a bold text - * is enabled and `false` otherwise. - * - `grayscaleChanged`: iOS-only event. Fires when the state of the gray scale toggle changes. - * The argument to the event handler is a boolean. The boolean is `true` when a gray scale - * is enabled and `false` otherwise. - * - `invertColorsChanged`: iOS-only event. Fires when the state of the invert colors toggle - * changes. The argument to the event handler is a boolean. The boolean is `true` when a invert - * colors is enabled and `false` otherwise. - * - `reduceTransparencyChanged`: iOS-only event. Fires when the state of the reduce transparency - * toggle changes. The argument to the event handler is a boolean. The boolean is `true` - * when a reduce transparency is enabled and `false` otherwise. - * - `announcementFinished`: iOS-only event. Fires when the screen reader has - * finished making an announcement. The argument to the event handler is a - * dictionary with these keys: - * - `announcement`: The string announced by the screen reader. - * - `success`: A boolean indicating whether the announcement was - * successfully made. - * - `darkerSystemColorsChanged`: iOS-only event. Fires when the state of the dark system colors - * toggle changes. The argument to the event handler is a boolean. The boolean is `true` when - * dark system colors is enabled and `false` otherwise. - * - * These events are only supported on Android: - * - * - `highTextContrastChanged`: Android-only event. Fires when the state of the high text contrast - * toggle changes. The argument to the event handler is a boolean. The boolean is `true` when - * high text contrast is enabled and `false` otherwise. - * - * See https://reactnative.dev/docs/accessibilityinfo#addeventlistener - */ - addEventListener>( - eventName: K, - // $FlowFixMe[incompatible-type] - Flow bug with unions and generics (T128099423) - handler: (...AccessibilityEventDefinitions[K]) => void, - ): EventSubscription { - const deviceEventName = EventNames.get(eventName); - return deviceEventName == null - ? {remove(): void {}} - : // $FlowFixMe[incompatible-type] - RCTDeviceEventEmitter.addListener(deviceEventName, handler); - }, - - /** - * Set accessibility focus to a React component. - * - * See https://reactnative.dev/docs/accessibilityinfo#setaccessibilityfocus - */ - setAccessibilityFocus(reactTag: number): void { - legacySendAccessibilityEvent(reactTag, 'focus'); - }, - /** * Send a named accessibility event to a HostComponent. */ @@ -457,69 +496,13 @@ const AccessibilityInfo = { // route through React renderer to distinguish between Fabric and non-Fabric handles sendAccessibilityEvent(handle, eventType); }, - - /** - * Post a string to be announced by the screen reader. - * - * See https://reactnative.dev/docs/accessibilityinfo#announceforaccessibility - */ - announceForAccessibility(announcement: string): void { - if (Platform.OS === 'android') { - NativeAccessibilityInfoAndroid?.announceForAccessibility(announcement); - } else { - NativeAccessibilityManagerIOS?.announceForAccessibility(announcement); - } - }, - - /** - * Post a string to be announced by the screen reader. - * - `announcement`: The string announced by the screen reader. - * - `options`: An object that configures the reading options. - * - `queue`: The announcement will be queued behind existing announcements. iOS only. - * - `priority`: The priority of the announcement. Possible values: 'low' | 'default' | 'high'. - * High priority announcements will interrupt any ongoing speech and cannot be interrupted. - * Default priority announcements will interrupt any ongoing speech but can be interrupted. - * Low priority announcements will not interrupt ongoing speech and can be interrupted. - * (iOS only). - */ - announceForAccessibilityWithOptions( - announcement: string, - options: {queue?: boolean, priority?: 'low' | 'default' | 'high'}, - ): void { - if (Platform.OS === 'android') { - NativeAccessibilityInfoAndroid?.announceForAccessibility(announcement); - } else { - if (NativeAccessibilityManagerIOS?.announceForAccessibilityWithOptions) { - NativeAccessibilityManagerIOS?.announceForAccessibilityWithOptions( - announcement, - options, - ); - } else { - NativeAccessibilityManagerIOS?.announceForAccessibility(announcement); - } - } - }, - /** - * Get the recommended timeout for changes to the UI needed by this user. + * Set accessibility focus to a React component. * - * See https://reactnative.dev/docs/accessibilityinfo#getrecommendedtimeoutmillis + * See https://reactnative.dev/docs/accessibilityinfo#setaccessibilityfocus */ - getRecommendedTimeoutMillis(originalTimeout: number): Promise { - if (Platform.OS === 'android') { - return new Promise((resolve, reject) => { - if (NativeAccessibilityInfoAndroid?.getRecommendedTimeoutMillis) { - NativeAccessibilityInfoAndroid.getRecommendedTimeoutMillis( - originalTimeout, - resolve, - ); - } else { - resolve(originalTimeout); - } - }); - } else { - return Promise.resolve(originalTimeout); - } + setAccessibilityFocus(reactTag: number): void { + legacySendAccessibilityEvent(reactTag, 'focus'); }, }; diff --git a/packages/react-native/Libraries/Components/Keyboard/Keyboard.js b/packages/react-native/Libraries/Components/Keyboard/Keyboard.js index 1dd4822eedd7..d50dc23fc83c 100644 --- a/packages/react-native/Libraries/Components/Keyboard/Keyboard.js +++ b/packages/react-native/Libraries/Components/Keyboard/Keyboard.js @@ -16,7 +16,7 @@ import dismissKeyboard from '../../Utilities/dismissKeyboard'; import Platform from '../../Utilities/Platform'; import NativeKeyboardObserver from './NativeKeyboardObserver'; -export type KeyboardEventName = $Keys; +export type KeyboardEventName = keyof KeyboardEventDefinitions; export type KeyboardEventEasing = | 'easeIn' @@ -146,7 +146,7 @@ class KeyboardImpl { * * @param {function} callback function to be called when the event fires. */ - addListener>( + addListener( eventType: K, listener: (...KeyboardEventDefinitions[K]) => mixed, context?: mixed, @@ -159,7 +159,7 @@ class KeyboardImpl { * * @param {string} eventType The native event string listeners are watching which will be removed. */ - removeAllListeners>(eventType: ?K): void { + removeAllListeners(eventType: ?K): void { this._emitter.removeAllListeners(eventType); } @@ -192,9 +192,9 @@ class KeyboardImpl { const {duration, easing} = event; if (duration != null && duration !== 0) { LayoutAnimation.configureNext({ - duration: duration, + duration, update: { - duration: duration, + duration, type: (easing != null && LayoutAnimation.Types[easing]) || 'keyboard', }, }); diff --git a/packages/react-native/Libraries/Components/ProgressBarAndroid/ProgressBarAndroid.js b/packages/react-native/Libraries/Components/ProgressBarAndroid/ProgressBarAndroid.js index 7d51999f5e6c..447327cb6695 100644 --- a/packages/react-native/Libraries/Components/ProgressBarAndroid/ProgressBarAndroid.js +++ b/packages/react-native/Libraries/Components/ProgressBarAndroid/ProgressBarAndroid.js @@ -21,7 +21,7 @@ export type {ProgressBarAndroidProps}; // of ProgressBarAndroidProps. TS's Omit does not distribute over unions, so // we define our own version which does. This does not affect Flow. // $FlowExpectedError[unclear-type] -type Omit = T extends any ? Pick, K>> : T; +type Omit = T extends any ? Pick> : T; /** * ProgressBarAndroid has been extracted from react-native core and will be removed in a future release. diff --git a/packages/react-native/Libraries/Components/StatusBar/StatusBar.js b/packages/react-native/Libraries/Components/StatusBar/StatusBar.js index 5cbc674ecf34..2bca72207f4d 100644 --- a/packages/react-native/Libraries/Components/StatusBar/StatusBar.js +++ b/packages/react-native/Libraries/Components/StatusBar/StatusBar.js @@ -20,7 +20,7 @@ import * as React from 'react'; /** * Status bar style */ -export type StatusBarStyle = $Keys<{ +export type StatusBarStyle = keyof { /** * Default status bar style (dark for iOS, light for Android) */ @@ -34,12 +34,12 @@ export type StatusBarStyle = $Keys<{ */ 'dark-content': string, ... -}>; +}; /** * Status bar animation */ -export type StatusBarAnimation = $Keys<{ +export type StatusBarAnimation = keyof { /** * No animation */ @@ -53,7 +53,7 @@ export type StatusBarAnimation = $Keys<{ */ slide: string, ... -}>; +}; export type StatusBarPropsAndroid = $ReadOnly<{ /** @@ -163,27 +163,27 @@ function createStackEntry(props: StatusBarProps): StackProps { backgroundColor: props.backgroundColor != null ? { - value: props.backgroundColor, animated, + value: props.backgroundColor, } : null, barStyle: props.barStyle != null ? { - value: props.barStyle, animated, + value: props.barStyle, } : null, - translucent: props.translucent, hidden: props.hidden != null ? { - value: props.hidden, animated, transition: showHideTransition, + value: props.hidden, } : null, networkActivityIndicatorVisible: props.networkActivityIndicatorVisible, + translucent: props.translucent, }; } @@ -239,9 +239,9 @@ class StatusBar extends React.Component { .DEFAULT_BACKGROUND_COLOR ?? 'black') : 'black', barStyle: 'default', - translucent: false, hidden: false, networkActivityIndicatorVisible: false, + translucent: false, }); // Timer for updating the native module values at the end of the frame. diff --git a/packages/react-native/Libraries/EventEmitter/NativeEventEmitter.js b/packages/react-native/Libraries/EventEmitter/NativeEventEmitter.js index 00c5ecf87793..986840c67d20 100644 --- a/packages/react-native/Libraries/EventEmitter/NativeEventEmitter.js +++ b/packages/react-native/Libraries/EventEmitter/NativeEventEmitter.js @@ -83,7 +83,7 @@ export default class NativeEventEmitter< } } - addListener>( + addListener( eventType: TEvent, listener: (...args: TEventToArgsMap[TEvent]) => mixed, context?: mixed, @@ -107,7 +107,7 @@ export default class NativeEventEmitter< }; } - emit>( + emit( eventType: TEvent, ...args: TEventToArgsMap[TEvent] ): void { @@ -116,9 +116,7 @@ export default class NativeEventEmitter< RCTDeviceEventEmitter.emit(eventType, ...args); } - removeAllListeners>( - eventType?: ?TEvent, - ): void { + removeAllListeners(eventType?: ?TEvent): void { invariant( eventType != null, '`NativeEventEmitter.removeAllListener()` requires a non-null argument.', @@ -127,7 +125,7 @@ export default class NativeEventEmitter< RCTDeviceEventEmitter.removeAllListeners(eventType); } - listenerCount>(eventType: TEvent): number { + listenerCount(eventType: TEvent): number { return RCTDeviceEventEmitter.listenerCount(eventType); } } diff --git a/packages/react-native/Libraries/EventEmitter/RCTDeviceEventEmitter.js b/packages/react-native/Libraries/EventEmitter/RCTDeviceEventEmitter.js index 8ec5f61eb8c3..e8e00e49d087 100644 --- a/packages/react-native/Libraries/EventEmitter/RCTDeviceEventEmitter.js +++ b/packages/react-native/Libraries/EventEmitter/RCTDeviceEventEmitter.js @@ -25,7 +25,7 @@ type RCTDeviceEventDefinitions = {[name: string]: Array}; */ class RCTDeviceEventEmitterImpl extends EventEmitter { // Add systrace to RCTDeviceEventEmitter.emit method for debugging - emit>( + emit( eventType: TEvent, ...args: RCTDeviceEventDefinitions[TEvent] ): void { diff --git a/packages/react-native/Libraries/EventEmitter/__mocks__/NativeEventEmitter.js b/packages/react-native/Libraries/EventEmitter/__mocks__/NativeEventEmitter.js index 0b0652798e1e..d69d8192c61a 100644 --- a/packages/react-native/Libraries/EventEmitter/__mocks__/NativeEventEmitter.js +++ b/packages/react-native/Libraries/EventEmitter/__mocks__/NativeEventEmitter.js @@ -22,7 +22,7 @@ export default class NativeEventEmitter< TEventToArgsMap: $ReadOnly>>, > implements IEventEmitter { - addListener>( + addListener( eventType: TEvent, listener: (...args: TEventToArgsMap[TEvent]) => mixed, context?: mixed, @@ -30,20 +30,18 @@ export default class NativeEventEmitter< return RCTDeviceEventEmitter.addListener(eventType, listener, context); } - emit>( + emit( eventType: TEvent, ...args: TEventToArgsMap[TEvent] ): void { RCTDeviceEventEmitter.emit(eventType, ...args); } - removeAllListeners>( - eventType?: ?TEvent, - ): void { + removeAllListeners(eventType?: ?TEvent): void { RCTDeviceEventEmitter.removeAllListeners(eventType); } - listenerCount>(eventType: TEvent): number { + listenerCount(eventType: TEvent): number { return RCTDeviceEventEmitter.listenerCount(eventType); } } diff --git a/packages/react-native/Libraries/Linking/Linking.js b/packages/react-native/Libraries/Linking/Linking.js index 016e3186a138..0facd07261fd 100644 --- a/packages/react-native/Libraries/Linking/Linking.js +++ b/packages/react-native/Libraries/Linking/Linking.js @@ -32,7 +32,7 @@ class LinkingImpl extends NativeEventEmitter { * * See https://reactnative.dev/docs/linking#addeventlistener */ - addEventListener>( + addEventListener( eventType: K, listener: (...LinkingEventDefinitions[K]) => mixed, ): EventSubscription { diff --git a/packages/react-native/Libraries/Network/RCTNetworking.android.js b/packages/react-native/Libraries/Network/RCTNetworking.android.js index 8b476e50def3..e9f521e802f1 100644 --- a/packages/react-native/Libraries/Network/RCTNetworking.android.js +++ b/packages/react-native/Libraries/Network/RCTNetworking.android.js @@ -48,7 +48,10 @@ const emitter = new NativeEventEmitter<$FlowFixMe>( * requestId to each network request that can be used to abort that request later on. */ const RCTNetworking = { - addListener>( + abortRequest(requestId: number) { + NativeNetworkingAndroid.abortRequest(requestId); + }, + addListener( eventType: K, listener: (...RCTNetworkingEventDefinitions[K]) => mixed, context?: mixed, @@ -56,7 +59,9 @@ const RCTNetworking = { // $FlowFixMe[incompatible-type] return emitter.addListener(eventType, listener, context); }, - + clearCookies(callback: (result: boolean) => void) { + NativeNetworkingAndroid.clearCookies(callback); + }, sendRequest( method: string, trackingName: string | void, @@ -84,7 +89,7 @@ const RCTNetworking = { url, requestId, convertHeadersMapToArray(headers), - {...body, trackingName, devToolsRequestId}, + {...body, devToolsRequestId, trackingName}, responseType, incrementalUpdates, timeout, @@ -92,14 +97,6 @@ const RCTNetworking = { ); callback(requestId); }, - - abortRequest(requestId: number) { - NativeNetworkingAndroid.abortRequest(requestId); - }, - - clearCookies(callback: (result: boolean) => void) { - NativeNetworkingAndroid.clearCookies(callback); - }, }; export default RCTNetworking; diff --git a/packages/react-native/Libraries/Network/RCTNetworking.ios.js b/packages/react-native/Libraries/Network/RCTNetworking.ios.js index 72669fbd6157..d06d94ec57c2 100644 --- a/packages/react-native/Libraries/Network/RCTNetworking.ios.js +++ b/packages/react-native/Libraries/Network/RCTNetworking.ios.js @@ -18,7 +18,10 @@ import {type RCTNetworkingEventDefinitions} from './RCTNetworkingEventDefinition import {type NativeResponseType} from './XMLHttpRequest'; const RCTNetworking = { - addListener>( + abortRequest(requestId: number) { + NativeNetworkingIOS.abortRequest(requestId); + }, + addListener( eventType: K, listener: (...RCTNetworkingEventDefinitions[K]) => mixed, context?: mixed, @@ -26,7 +29,9 @@ const RCTNetworking = { // $FlowFixMe[incompatible-type] return RCTDeviceEventEmitter.addListener(eventType, listener, context); }, - + clearCookies(callback: (result: boolean) => void) { + NativeNetworkingIOS.clearCookies(callback); + }, sendRequest( method: string, trackingName: string | void, @@ -44,27 +49,19 @@ const RCTNetworking = { global.__NETWORK_REPORTER__?.createDevToolsRequestId(); NativeNetworkingIOS.sendRequest( { - method, - url, data: {...body, trackingName}, headers, - responseType, incrementalUpdates, + method, + responseType, timeout, - withCredentials, unstable_devToolsRequestId: devToolsRequestId, + url, + withCredentials, }, callback, ); }, - - abortRequest(requestId: number) { - NativeNetworkingIOS.abortRequest(requestId); - }, - - clearCookies(callback: (result: boolean) => void) { - NativeNetworkingIOS.clearCookies(callback); - }, }; export default RCTNetworking; diff --git a/packages/react-native/Libraries/Network/RCTNetworking.js.flow b/packages/react-native/Libraries/Network/RCTNetworking.js.flow index a5dab0519433..67e7086c90cd 100644 --- a/packages/react-native/Libraries/Network/RCTNetworking.js.flow +++ b/packages/react-native/Libraries/Network/RCTNetworking.js.flow @@ -16,7 +16,7 @@ import type {RCTNetworkingEventDefinitions} from './RCTNetworkingEventDefinition import type {NativeResponseType} from './XMLHttpRequest'; declare const RCTNetworking: interface { - addListener>( + addListener( eventType: K, // $FlowFixMe[invalid-computed-prop] listener: (...RCTNetworkingEventDefinitions[K]) => mixed, diff --git a/packages/react-native/Libraries/PushNotificationIOS/PushNotificationIOS.js b/packages/react-native/Libraries/PushNotificationIOS/PushNotificationIOS.js index 26e1dacfb47c..ddc0389e0b7d 100644 --- a/packages/react-native/Libraries/PushNotificationIOS/PushNotificationIOS.js +++ b/packages/react-native/Libraries/PushNotificationIOS/PushNotificationIOS.js @@ -89,7 +89,7 @@ export type FetchResult = { /** * An event emitted by PushNotificationIOS. */ -export type PushNotificationEventName = $Keys<{ +export type PushNotificationEventName = keyof { /** * Fired when a remote notification is received. The handler will be invoked * with an instance of `PushNotificationIOS`. This will handle notifications @@ -116,7 +116,7 @@ export type PushNotificationEventName = $Keys<{ */ registrationError: string, ... -}>; +}; export interface PushNotification { /** diff --git a/packages/react-native/Libraries/ReactNative/RendererImplementation.js b/packages/react-native/Libraries/ReactNative/RendererImplementation.js index 770ac325093f..89b624b18b03 100644 --- a/packages/react-native/Libraries/ReactNative/RendererImplementation.js +++ b/packages/react-native/Libraries/ReactNative/RendererImplementation.js @@ -37,11 +37,11 @@ function getPaperRenderer(): ReactNativeType { return cachedPaperRenderer; } -const getMethod: (>( +const getMethod: (( () => ReactFabricType, MethodName, ) => ReactFabricType[MethodName]) & - (>( + (( () => ReactNativeType, MethodName, ) => ReactNativeType[MethodName]) = (getRenderer, methodName) => { @@ -59,13 +59,13 @@ const getMethod: (>( }; }; -function getFabricMethod>( +function getFabricMethod( methodName: MethodName, ): ReactFabricType[MethodName] { return getMethod(getFabricRenderer, methodName); } -function getPaperMethod>( +function getPaperMethod( methodName: MethodName, ): ReactNativeType[MethodName] { return getMethod(getPaperRenderer, methodName); @@ -92,8 +92,8 @@ export function renderElement({ cachedFabricRender(element, rootTag, null, useConcurrentRoot, { onCaughtError, - onUncaughtError, onRecoverableError, + onUncaughtError, }); } else { if (cachedPaperRender == null) { @@ -102,8 +102,8 @@ export function renderElement({ cachedPaperRender(element, rootTag, undefined, { onCaughtError, - onUncaughtError, onRecoverableError, + onUncaughtError, }); } } diff --git a/packages/react-native/Libraries/StyleSheet/StyleSheet.js b/packages/react-native/Libraries/StyleSheet/StyleSheet.js index 3bbfa9031f30..23dedbe8552f 100644 --- a/packages/react-native/Libraries/StyleSheet/StyleSheet.js +++ b/packages/react-native/Libraries/StyleSheet/StyleSheet.js @@ -118,7 +118,7 @@ export type DangerouslyImpreciseStyleProp = * This will correctly give you the type 'absolute' | 'relative' */ export type TypeForStyleKey< - +key: $Keys<____DangerouslyImpreciseStyle_Internal>, + +key: keyof ____DangerouslyImpreciseStyle_Internal, > = ____DangerouslyImpreciseStyle_Internal[key]; /** diff --git a/packages/react-native/Libraries/StyleSheet/StyleSheet.js.flow b/packages/react-native/Libraries/StyleSheet/StyleSheet.js.flow index 73ebfd9bfb0a..f72489b8815e 100644 --- a/packages/react-native/Libraries/StyleSheet/StyleSheet.js.flow +++ b/packages/react-native/Libraries/StyleSheet/StyleSheet.js.flow @@ -119,7 +119,7 @@ export type DangerouslyImpreciseStyleProp = * This will correctly give you the type 'absolute' | 'relative' */ export type TypeForStyleKey< - +key: $Keys<____DangerouslyImpreciseStyle_Internal>, + +key: keyof ____DangerouslyImpreciseStyle_Internal, > = ____DangerouslyImpreciseStyle_Internal[key]; /** diff --git a/packages/react-native/Libraries/StyleSheet/private/_TransformStyle.js b/packages/react-native/Libraries/StyleSheet/private/_TransformStyle.js index ab847c68f6fa..bda45fa81d6b 100644 --- a/packages/react-native/Libraries/StyleSheet/private/_TransformStyle.js +++ b/packages/react-native/Libraries/StyleSheet/private/_TransformStyle.js @@ -13,10 +13,10 @@ import type AnimatedNode from '../../Animated/nodes/AnimatedNode'; // Helper types to enforce that a single key is used in a transform object // after generating a TypeScript definition file from the Flow types. // $FlowExpectedError[unclear-type] -type KeysOfUnion = T extends any ? $Keys : empty; +type KeysOfUnion = T extends any ? keyof T : empty; // $FlowExpectedError[unclear-type] type ValueOfUnion = T extends any - ? K extends $Keys + ? K extends keyof T ? T[K] : empty : empty; diff --git a/packages/react-native/Libraries/Types/ReactDevToolsTypes.js b/packages/react-native/Libraries/Types/ReactDevToolsTypes.js index effa843e2d67..21374dc03e7c 100644 --- a/packages/react-native/Libraries/Types/ReactDevToolsTypes.js +++ b/packages/react-native/Libraries/Types/ReactDevToolsTypes.js @@ -34,12 +34,12 @@ export type ReactDevToolsAgentEvents = { export type ReactDevToolsAgent = { selectNode(node: mixed): void, stopInspectingNative(value: boolean): void, - addListener>( + addListener( event: Event, listener: (...ReactDevToolsAgentEvents[Event]) => void, ): void, removeListener( - event: $Keys, + event: keyof ReactDevToolsAgentEvents, listener: () => void, ): void, }; diff --git a/packages/react-native/Libraries/Utilities/codegenNativeCommands.js b/packages/react-native/Libraries/Utilities/codegenNativeCommands.js index 6f9c0a115a18..42edce66abff 100644 --- a/packages/react-native/Libraries/Utilities/codegenNativeCommands.js +++ b/packages/react-native/Libraries/Utilities/codegenNativeCommands.js @@ -15,9 +15,9 @@ type NativeCommandsOptions = $ReadOnly<{ }>; function codegenNativeCommands( - options: NativeCommandsOptions<$Keys>, + options: NativeCommandsOptions, ): T { - const commandObj: {[$Keys]: (...$ReadOnlyArray) => void} = {}; + const commandObj: {[keyof T]: (...$ReadOnlyArray) => void} = {}; options.supportedCommands.forEach(command => { // $FlowFixMe[missing-local-annot] diff --git a/packages/react-native/Libraries/vendor/emitter/EventEmitter.js b/packages/react-native/Libraries/vendor/emitter/EventEmitter.js index 236f963dc082..969b99ca6047 100644 --- a/packages/react-native/Libraries/vendor/emitter/EventEmitter.js +++ b/packages/react-native/Libraries/vendor/emitter/EventEmitter.js @@ -18,20 +18,20 @@ export interface EventSubscription { export interface IEventEmitter< TEventToArgsMap: $ReadOnly>>, > { - addListener>( + addListener( eventType: TEvent, listener: (...args: TEventToArgsMap[TEvent]) => mixed, context?: mixed, ): EventSubscription; - emit>( + emit( eventType: TEvent, ...args: TEventToArgsMap[TEvent] ): void; - removeAllListeners>(eventType?: ?TEvent): void; + removeAllListeners(eventType?: ?TEvent): void; - listenerCount>(eventType: TEvent): number; + listenerCount(eventType: TEvent): number; } interface Registration { @@ -83,7 +83,7 @@ export default class EventEmitter< * Registers a listener that is called when the supplied event is emitted. * Returns a subscription that has a `remove` method to undo registration. */ - addListener>( + addListener( eventType: TEvent, listener: (...args: TEventToArgsMap[TEvent]) => mixed, context: mixed, @@ -95,7 +95,7 @@ export default class EventEmitter< } const registrations = allocate< TEventToArgsMap, - $Keys, + keyof TEventToArgsMap, TEventToArgsMap[TEvent], >(this.#registry, eventType); const registration: Registration = { @@ -116,7 +116,7 @@ export default class EventEmitter< * If a listener modifies the listeners registered for the same event, those * changes will not be reflected in the current invocation of `emit`. */ - emit>( + emit( eventType: TEvent, ...args: TEventToArgsMap[TEvent] ): void { @@ -135,9 +135,7 @@ export default class EventEmitter< /** * Removes all registered listeners. */ - removeAllListeners>( - eventType?: ?TEvent, - ): void { + removeAllListeners(eventType?: ?TEvent): void { if (eventType == null) { // $FlowFixMe[incompatible-type] this.#registry = {}; @@ -149,7 +147,7 @@ export default class EventEmitter< /** * Returns the number of registered listeners for the supplied event. */ - listenerCount>(eventType: TEvent): number { + listenerCount(eventType: TEvent): number { const registrations: ?Set> = this.#registry[eventType]; return registrations == null ? 0 : registrations.size; @@ -158,7 +156,7 @@ export default class EventEmitter< function allocate< TEventToArgsMap: $ReadOnly>>, - TEvent: $Keys, + TEvent: keyof TEventToArgsMap, TEventArgs: TEventToArgsMap[TEvent], >( registry: Registry, diff --git a/packages/react-native/src/private/__tests__/MemoryBaseline-itest.js b/packages/react-native/src/private/__tests__/MemoryBaseline-itest.js index dab58d04617a..a3718253c7f7 100644 --- a/packages/react-native/src/private/__tests__/MemoryBaseline-itest.js +++ b/packages/react-native/src/private/__tests__/MemoryBaseline-itest.js @@ -28,17 +28,17 @@ declare var performance: Performance; * and set a new baseline. Otherwise, please try to optimize your code. */ const MEMORY_LIMITS_KB = { - environmentSetup: { - dev: 1000, - opt: 500, - }, basicSurfaceRender: { dev: 1200, opt: 700, }, + environmentSetup: { + dev: 1000, + opt: 500, + }, }; -function limitFor(scenario: $Keys): number { +function limitFor(scenario: keyof typeof MEMORY_LIMITS_KB): number { return MEMORY_LIMITS_KB[scenario][__DEV__ ? 'dev' : 'opt']; } diff --git a/packages/react-native/src/private/__tests__/utilities/accessibilityPropsSuite.js b/packages/react-native/src/private/__tests__/utilities/accessibilityPropsSuite.js index e28d6acf2c8b..9596c34c8edb 100644 --- a/packages/react-native/src/private/__tests__/utilities/accessibilityPropsSuite.js +++ b/packages/react-native/src/private/__tests__/utilities/accessibilityPropsSuite.js @@ -118,7 +118,7 @@ let root: Root; function getAccessibilityProp( content: React.MixedElement, - name: $Keys, + name: keyof AccessibilityProps, ) { Fantom.runTask(() => { root.render(content); @@ -128,7 +128,7 @@ function getAccessibilityProp( function getAccessibilityProps( content: React.MixedElement, - names: $ReadOnlyArray<$Keys>, + names: $ReadOnlyArray, ) { Fantom.runTask(() => { root.render(content); @@ -238,8 +238,8 @@ export default function accessibilityPropsSuite( ['accessibilityLabel', 'accessibilityHint'], ), ).toEqual({ - accessibilityLabel: 'Touchable', accessibilityHint: 'Can be pressed to interact', + accessibilityLabel: 'Touchable', }); }); }); @@ -319,7 +319,7 @@ export default function accessibilityPropsSuite( , diff --git a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlagsBase.js b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlagsBase.js index c126e158848c..fec4641a4dc7 100644 --- a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlagsBase.js +++ b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlagsBase.js @@ -52,7 +52,7 @@ function createGetter( } export function createJavaScriptFlagGetter< - K: $Keys, + K: keyof ReactNativeFeatureFlagsJsOnly, >( configName: K, defaultValue: ReturnType, @@ -69,7 +69,7 @@ export function createJavaScriptFlagGetter< type NativeFeatureFlags = $NonMaybeType; -export function createNativeFlagGetter>( +export function createNativeFlagGetter( configName: K, defaultValue: ReturnType<$NonMaybeType>, skipUnavailableNativeModuleError: boolean = false, diff --git a/packages/rn-tester/js/utils/RNTesterNavigationReducer.js b/packages/rn-tester/js/utils/RNTesterNavigationReducer.js index a952455b82fc..c19ca84d0ec3 100644 --- a/packages/rn-tester/js/utils/RNTesterNavigationReducer.js +++ b/packages/rn-tester/js/utils/RNTesterNavigationReducer.js @@ -14,12 +14,12 @@ import type { } from '../types/RNTesterTypes'; export const RNTesterNavigationActionsType = { - NAVBAR_PRESS: 'NAVBAR_PRESS', BACK_BUTTON_PRESS: 'BACK_BUTTON_PRESS', - MODULE_CARD_PRESS: 'MODULE_CARD_PRESS', EXAMPLE_CARD_PRESS: 'EXAMPLE_CARD_PRESS', EXAMPLE_OPEN_URL_REQUEST: 'EXAMPLE_OPEN_URL_REQUEST', + MODULE_CARD_PRESS: 'MODULE_CARD_PRESS', NAVBAR_OPEN_MODULE_PRESS: 'NAVBAR_OPEN_MODULE_PRESS', + NAVBAR_PRESS: 'NAVBAR_PRESS', } as const; const getUpdatedRecentlyUsed = ({ @@ -34,7 +34,7 @@ const getUpdatedRecentlyUsed = ({ const updatedRecentlyUsed = recentlyUsed ? {...recentlyUsed} : // $FlowFixMe[missing-empty-array-annot] - {components: [], apis: []}; + {apis: [], components: []}; if (!exampleType || !key) { return updatedRecentlyUsed; @@ -55,7 +55,7 @@ const getUpdatedRecentlyUsed = ({ export const RNTesterNavigationReducer = ( state: RNTesterNavigationState, - action: {type: $Keys, data?: any}, + action: {type: keyof typeof RNTesterNavigationActionsType, data?: any}, ): RNTesterNavigationState => { const { data: { @@ -71,34 +71,34 @@ export const RNTesterNavigationReducer = ( case RNTesterNavigationActionsType.NAVBAR_PRESS: return { ...state, + activeModuleExampleKey: null, activeModuleKey: null, activeModuleTitle: null, - activeModuleExampleKey: null, - screen, hadDeepLink: false, + screen, }; case RNTesterNavigationActionsType.NAVBAR_OPEN_MODULE_PRESS: return { ...state, + activeModuleExampleKey: null, activeModuleKey: key, activeModuleTitle: title, - activeModuleExampleKey: null, - screen, hadDeepLink: false, + screen, }; case RNTesterNavigationActionsType.MODULE_CARD_PRESS: return { ...state, + activeModuleExampleKey: null, activeModuleKey: key, activeModuleTitle: title, - activeModuleExampleKey: null, hadDeepLink: false, // $FlowFixMe[incompatible-return] recentlyUsed: getUpdatedRecentlyUsed({ - exampleType: exampleType, - key: key, + exampleType, + key, recentlyUsed: state.recentlyUsed, }), }; @@ -106,8 +106,8 @@ export const RNTesterNavigationReducer = ( case RNTesterNavigationActionsType.EXAMPLE_CARD_PRESS: return { ...state, - hadDeepLink: false, activeModuleExampleKey: key, + hadDeepLink: false, }; case RNTesterNavigationActionsType.BACK_BUTTON_PRESS: @@ -131,9 +131,9 @@ export const RNTesterNavigationReducer = ( case RNTesterNavigationActionsType.EXAMPLE_OPEN_URL_REQUEST: return { ...state, + activeModuleExampleKey: exampleKey, activeModuleKey: key, activeModuleTitle: title, - activeModuleExampleKey: exampleKey, hadDeepLink: true, screen: 'components', }; diff --git a/packages/virtualized-lists/Lists/StateSafePureComponent.js b/packages/virtualized-lists/Lists/StateSafePureComponent.js index bf75a6de848b..3b41178a4094 100644 --- a/packages/virtualized-lists/Lists/StateSafePureComponent.js +++ b/packages/virtualized-lists/Lists/StateSafePureComponent.js @@ -32,7 +32,7 @@ export default class StateSafePureComponent< } // $FlowFixMe[incompatible-type] - setState>( + setState( partialState: ?(Pick | ((State, Props) => ?Pick)), callback?: () => mixed, ): void { diff --git a/scripts/build/config.js b/scripts/build/config.js index 04829f3d5f2e..8f029197dd40 100644 --- a/scripts/build/config.js +++ b/scripts/build/config.js @@ -70,7 +70,7 @@ const defaultBuildOptions = { }; function getBuildOptions( - packageName: $Keys, + packageName: keyof BuildConfig['packages'], ): Required { return { ...defaultBuildOptions, @@ -79,7 +79,7 @@ function getBuildOptions( } function getBabelConfig( - packageName: $Keys, + packageName: keyof BuildConfig['packages'], ): BabelCoreOptions { const {target} = getBuildOptions(packageName); @@ -90,7 +90,7 @@ function getBabelConfig( } function getTypeScriptCompilerOptions( - packageName: $Keys, + packageName: keyof BuildConfig['packages'], ): Object { const {target} = getBuildOptions(packageName);