@samitouri / QOS-React / commits / 4049cfeeab

Update Flow to 0.273 (#34274)

This version introduces "Natural Inference" which requires a couple more type annotations to make Flow pass.

Jan Kassens committed Aug 22, 2025 at 16:58 UTC 4049cfeeab33146e02b0721477fd5f2020f76a04
15 files changed +40 -34
.eslintrc.js
+1
@@ -565,6 +565,7 @@ module.exports = {
565 BigInt: 'readonly',
566 BigInt64Array: 'readonly',
567 BigUint64Array: 'readonly',
568 + CacheType: 'readonly',
569 Class: 'readonly',
570 ClientRect: 'readonly',
571 CopyInspectedElementPath: 'readonly',
package.json
+2 -2
@@ -74,8 +74,8 @@
74 "eslint-plugin-react-internal": "link:./scripts/eslint-rules",
75 "fbjs-scripts": "^3.0.1",
76 "filesize": "^6.0.1",
77 - "flow-bin": "^0.272",
78 - "flow-remove-types": "^2.272",
77 + "flow-bin": "^0.273",
78 + "flow-remove-types": "^2.273",
79 "flow-typed": "^4.1.1",
80 "glob": "^7.1.6",
81 "glob-stream": "^6.1.0",
packages/react-devtools-shared/src/backend/fiber/renderer.js
+1 -1
@@ -6705,7 +6705,7 @@ export function attach(
6705 if (isMostRecentlyInspectedElement(id) && !forceFullData) {
6706 if (!hasElementUpdatedSinceLastInspected) {
6707 if (path !== null) {
6708 - let secondaryCategory = null;
6708 + let secondaryCategory: 'suspendedBy' | 'hooks' | null = null;
6709 if (path[0] === 'hooks') {
6710 secondaryCategory = 'hooks';
6711 }
packages/react-devtools-shared/src/hookNamesCache.js
+1 -1
@@ -103,7 +103,7 @@ export function loadHookNames(
103
104 let timeoutID: $FlowFixMe | null;
105 let didTimeout = false;
106 - let status = 'unknown';
106 + let status: 'success' | 'error' | 'timeout' | 'unknown' = 'unknown';
107 let resolvedHookNames: HookNames | null = null;
108
109 const wake = () => {
packages/react-devtools-shared/src/hooks/parseHookNames/loadSourceAndMetadata.js
+1 -1
@@ -64,7 +64,7 @@ import type {FetchFileWithCaching} from 'react-devtools-shared/src/devtools/view
64
65 // Prefer a cached albeit stale response to reduce download time.
66 // We wouldn't want to load/parse a newer version of the source (even if one existed).
67 -const FETCH_OPTIONS = {cache: 'force-cache'};
67 +const FETCH_OPTIONS = {cache: 'force-cache' as CacheType};
68
69 const MAX_SOURCE_LENGTH = 100_000_000;
70
packages/react-devtools-timeline/src/import-worker/preprocessData.js
+3 -3
@@ -509,7 +509,7 @@ function processTimelineEvent(
509 } else if (name.startsWith('--schedule-forced-update-')) {
510 const [laneBitmaskString, componentName] = name.slice(25).split('-');
511
512 - const forceUpdateEvent = {
512 + const forceUpdateEvent: SchedulingEvent = {
513 type: 'schedule-force-update',
514 lanes: getLanesFromTransportDecimalBitmask(laneBitmaskString),
515 componentName,
@@ -527,7 +527,7 @@ function processTimelineEvent(
527 } else if (name.startsWith('--schedule-state-update-')) {
528 const [laneBitmaskString, componentName] = name.slice(24).split('-');
529
530 - const stateUpdateEvent = {
530 + const stateUpdateEvent: SchedulingEvent = {
531 type: 'schedule-state-update',
532 lanes: getLanesFromTransportDecimalBitmask(laneBitmaskString),
533 componentName,
@@ -578,7 +578,7 @@ function processTimelineEvent(
578 // We can't know if they'll be resolved or not at this point.
579 // We'll just give them a default (fake) duration width.
580
581 - const suspenseEvent = {
581 + const suspenseEvent: SuspenseEvent = {
582 componentName,
583 depth,
584 duration: null,
packages/react-dom-bindings/src/client/inputValueTracking.js
+6 -3
@@ -140,7 +140,7 @@ export function trackHydrated(
140 return false;
141 }
142
143 - let valueField;
143 + let valueField: 'checked' | 'value';
144 let expectedValue;
145 if (isCheckable(node)) {
146 valueField = 'checked';
@@ -150,8 +150,11 @@ export function trackHydrated(
150 valueField = 'value';
151 expectedValue = initialValue;
152 }
153 - // eslint-disable-next-line react-internal/safe-string-coercion
154 - const currentValue = '' + (node[valueField]: any);
153 + const currentValue =
154 + // eslint-disable-next-line react-internal/safe-string-coercion
155 + '' +
156 + (// $FlowFixMe[prop-missing]
157 + node[valueField]: any);
158 node._valueTracker = trackValueOnNode(node, valueField, expectedValue);
159 return currentValue !== expectedValue;
160 }
packages/react-dom-bindings/src/events/SyntheticEvent.js
+7 -7
@@ -146,7 +146,7 @@ function createSyntheticEvent(Interface: EventInterfaceType) {
146 * @interface Event
147 * @see http://www.w3.org/TR/DOM-Level-3-Events/
148 */
149 -const EventInterface = {
149 +const EventInterface: EventInterfaceType = {
150 eventPhase: 0,
151 bubbles: 0,
152 cancelable: 0,
@@ -442,7 +442,7 @@ function getEventModifierState(nativeEvent: {[propName: string]: mixed}) {
442 * @interface KeyboardEvent
443 * @see http://www.w3.org/TR/DOM-Level-3-Events/
444 */
445 -const KeyboardEventInterface = {
445 +const KeyboardEventInterface: EventInterfaceType = {
446 ...UIEventInterface,
447 key: getEventKey,
448 code: 0,
@@ -505,7 +505,7 @@ export const SyntheticKeyboardEvent: $FlowFixMe = createSyntheticEvent(
505 * @interface PointerEvent
506 * @see http://www.w3.org/TR/pointerevents/
507 */
508 -const PointerEventInterface = {
508 +const PointerEventInterface: EventInterfaceType = {
509 ...MouseEventInterface,
510 pointerId: 0,
511 width: 0,
@@ -526,7 +526,7 @@ export const SyntheticPointerEvent: $FlowFixMe = createSyntheticEvent(
526 * @interface TouchEvent
527 * @see http://www.w3.org/TR/touch-events/
528 */
529 -const TouchEventInterface = {
529 +const TouchEventInterface: EventInterfaceType = {
530 ...UIEventInterface,
531 touches: 0,
532 targetTouches: 0,
@@ -545,7 +545,7 @@ export const SyntheticTouchEvent: $FlowFixMe =
545 * @see http://www.w3.org/TR/2009/WD-css3-transitions-20090320/#transition-events-
546 * @see https://developer.mozilla.org/en-US/docs/Web/API/TransitionEvent
547 */
548 -const TransitionEventInterface = {
548 +const TransitionEventInterface: EventInterfaceType = {
549 ...EventInterface,
550 propertyName: 0,
551 elapsedTime: 0,
@@ -559,7 +559,7 @@ export const SyntheticTransitionEvent: $FlowFixMe = createSyntheticEvent(
559 * @interface WheelEvent
560 * @see http://www.w3.org/TR/DOM-Level-3-Events/
561 */
562 -const WheelEventInterface = {
562 +const WheelEventInterface: EventInterfaceType = {
563 ...MouseEventInterface,
564 deltaX(event: {[propName: string]: mixed}) {
565 return 'deltaX' in event
@@ -594,7 +594,7 @@ const WheelEventInterface = {
594 export const SyntheticWheelEvent: $FlowFixMe =
595 createSyntheticEvent(WheelEventInterface);
596
597 -const ToggleEventInterface = {
597 +const ToggleEventInterface: EventInterfaceType = {
598 ...EventInterface,
599 newState: 0,
600 oldState: 0,
packages/react-dom-bindings/src/shared/ReactDOMFormActions.js
+1 -1
@@ -31,7 +31,7 @@ export type FormStatus = FormStatusPending | FormStatusNotPending;
31
32 // Since the "not pending" value is always the same, we can reuse the
33 // same object across all transitions.
34 -const sharedNotPendingObject = {
34 +const sharedNotPendingObject: FormStatusNotPending = {
35 pending: false,
36 data: null,
37 method: null,
packages/react-native-renderer/src/legacy-events/ResponderTouchHistoryStore.js
+1
@@ -207,6 +207,7 @@ const ResponderTouchHistoryStore = {
207 touchHistory.numberActiveTouches = nativeEvent.touches.length;
208 if (touchHistory.numberActiveTouches === 1) {
209 touchHistory.indexOfSingleActiveTouch =
210 + // $FlowFixMe[incompatible-type] might be null according to type
211 nativeEvent.touches[0].identifier;
212 }
213 } else if (isEndish(topLevelType)) {
packages/react-reconciler/src/ReactFiberCommitWork.js
+2 -2
@@ -5020,7 +5020,7 @@ function commitPassiveUnmountInsideDeletedTreeOnFiber(
5020 const instance: OffscreenInstance = offscreenFiber.stateNode;
5021 const transitions = instance._transitions;
5022 if (transitions !== null) {
5023 - const abortReason = {
5023 + const abortReason: TransitionAbort = {
5024 reason: 'suspense',
5025 name: current.memoizedProps.name || null,
5026 };
@@ -5061,7 +5061,7 @@ function commitPassiveUnmountInsideDeletedTreeOnFiber(
5061 const instance: TracingMarkerInstance = current.stateNode;
5062 const transitions = instance.transitions;
5063 if (transitions !== null) {
5064 - const abortReason = {
5064 + const abortReason: TransitionAbort = {
5065 reason: 'marker',
5066 name: current.memoizedProps.name,
5067 };
packages/react-test-renderer/src/ReactTestRenderer.js
+2 -1
@@ -9,6 +9,7 @@
9
10 import type {Fiber, FiberRoot} from 'react-reconciler/src/ReactInternalTypes';
11 import type {
12 + Container,
13 PublicInstance,
14 Instance,
15 TextInstance,
@@ -505,7 +506,7 @@ function create(
506 isStrictMode = true;
507 }
508 }
508 - let container = {
509 + let container: Container = {
510 children: ([]: Array<Instance | TextInstance>),
511 createNodeMock,
512 tag: 'CONTAINER',
packages/scheduler/src/forks/SchedulerPostTask.js
+1 -1
@@ -76,7 +76,7 @@ export function unstable_scheduleCallback<T>(
76 callback: SchedulerCallback<T>,
77 options?: {delay?: number},
78 ): CallbackNode {
79 - let postTaskPriority;
79 + let postTaskPriority: PostTaskPriorityLevel;
80 switch (priorityLevel) {
81 case ImmediatePriority:
82 case UserBlockingPriority:
packages/use-sync-external-store/src/useSyncExternalStoreWithSelector.js
+6 -6
@@ -23,8 +23,7 @@ export function useSyncExternalStoreWithSelector<Snapshot, Selection>(
23 selector: (snapshot: Snapshot) => Selection,
24 isEqual?: (a: Selection, b: Selection) => boolean,
25 ): Selection {
26 - // Use this to track the rendered snapshot.
27 - const instRef = useRef<
26 + type Inst =
27 | {
28 hasValue: true,
29 value: Selection,
@@ -32,10 +31,11 @@ export function useSyncExternalStoreWithSelector<Snapshot, Selection>(
31 | {
32 hasValue: false,
33 value: null,
35 - }
36 - | null,
37 - >(null);
38 - let inst;
34 + };
35 +
36 + // Use this to track the rendered snapshot.
37 + const instRef = useRef<Inst | null>(null);
38 + let inst: Inst;
39 if (instRef.current === null) {
40 inst = {
41 hasValue: false,
yarn.lock
+5 -5
@@ -9298,12 +9298,12 @@ flatted@^3.2.9:
9298 resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a"
9299 integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==
9300
9301 -flow-bin@^0.272:
9302 - version "0.272.2"
9303 - resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.272.2.tgz#918fc58dc7a99725a83314f453d3e49a56aebdc5"
9304 - integrity sha512-Rf8UG1biRBUGGh6qN7Ua2Y2lJRpR8Pbzby5kfHQ5m5SgjC5eOPw3Qjbrheb9ec5oU4L1gCOXRYbkbpr02PRUBw==
9301 +flow-bin@^0.273:
9302 + version "0.273.1"
9303 + resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.273.1.tgz#18621f169ecbabe3656c56980ebaabc439ee76c1"
9304 + integrity sha512-OlJkNCSd+i6z5xDoyGiS+3X5xYQx+vVUY2iUw6cHJR0LK3ttyA1wkiI93OuBALhLhF91KayzGhRSzXHqA75iUw==
9305
9306 -flow-remove-types@^2.272:
9306 +flow-remove-types@^2.273:
9307 version "2.279.0"
9308 resolved "https://registry.yarnpkg.com/flow-remove-types/-/flow-remove-types-2.279.0.tgz#3a3388d9158eba0f82c40d80d31d9640b883a3f5"
9309 integrity sha512-bPFloMR/A2b/r/sIsf7Ix0LaMicCJNjwhXc4xEEQVzJCIz5u7C7XDaEOXOiqveKlCYK7DcBNn6R01Cbbc9gsYA==