Update Flow to 0.273 (#34274)

This version introduces "Natural Inference" which requires a couple more
type annotations to make Flow pass.
This commit is contained in:
Jan Kassens 2025-08-22 16:58:01 -04:00 committed by GitHub
parent e67e3bed92
commit 4049cfeeab
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 40 additions and 34 deletions

View File

@ -565,6 +565,7 @@ module.exports = {
BigInt: 'readonly',
BigInt64Array: 'readonly',
BigUint64Array: 'readonly',
CacheType: 'readonly',
Class: 'readonly',
ClientRect: 'readonly',
CopyInspectedElementPath: 'readonly',

View File

@ -74,8 +74,8 @@
"eslint-plugin-react-internal": "link:./scripts/eslint-rules",
"fbjs-scripts": "^3.0.1",
"filesize": "^6.0.1",
"flow-bin": "^0.272",
"flow-remove-types": "^2.272",
"flow-bin": "^0.273",
"flow-remove-types": "^2.273",
"flow-typed": "^4.1.1",
"glob": "^7.1.6",
"glob-stream": "^6.1.0",

View File

@ -6705,7 +6705,7 @@ export function attach(
if (isMostRecentlyInspectedElement(id) && !forceFullData) {
if (!hasElementUpdatedSinceLastInspected) {
if (path !== null) {
let secondaryCategory = null;
let secondaryCategory: 'suspendedBy' | 'hooks' | null = null;
if (path[0] === 'hooks') {
secondaryCategory = 'hooks';
}

View File

@ -103,7 +103,7 @@ export function loadHookNames(
let timeoutID: $FlowFixMe | null;
let didTimeout = false;
let status = 'unknown';
let status: 'success' | 'error' | 'timeout' | 'unknown' = 'unknown';
let resolvedHookNames: HookNames | null = null;
const wake = () => {

View File

@ -64,7 +64,7 @@ import type {FetchFileWithCaching} from 'react-devtools-shared/src/devtools/view
// Prefer a cached albeit stale response to reduce download time.
// We wouldn't want to load/parse a newer version of the source (even if one existed).
const FETCH_OPTIONS = {cache: 'force-cache'};
const FETCH_OPTIONS = {cache: 'force-cache' as CacheType};
const MAX_SOURCE_LENGTH = 100_000_000;

View File

@ -509,7 +509,7 @@ function processTimelineEvent(
} else if (name.startsWith('--schedule-forced-update-')) {
const [laneBitmaskString, componentName] = name.slice(25).split('-');
const forceUpdateEvent = {
const forceUpdateEvent: SchedulingEvent = {
type: 'schedule-force-update',
lanes: getLanesFromTransportDecimalBitmask(laneBitmaskString),
componentName,
@ -527,7 +527,7 @@ function processTimelineEvent(
} else if (name.startsWith('--schedule-state-update-')) {
const [laneBitmaskString, componentName] = name.slice(24).split('-');
const stateUpdateEvent = {
const stateUpdateEvent: SchedulingEvent = {
type: 'schedule-state-update',
lanes: getLanesFromTransportDecimalBitmask(laneBitmaskString),
componentName,
@ -578,7 +578,7 @@ function processTimelineEvent(
// We can't know if they'll be resolved or not at this point.
// We'll just give them a default (fake) duration width.
const suspenseEvent = {
const suspenseEvent: SuspenseEvent = {
componentName,
depth,
duration: null,

View File

@ -140,7 +140,7 @@ export function trackHydrated(
return false;
}
let valueField;
let valueField: 'checked' | 'value';
let expectedValue;
if (isCheckable(node)) {
valueField = 'checked';
@ -150,8 +150,11 @@ export function trackHydrated(
valueField = 'value';
expectedValue = initialValue;
}
const currentValue =
// eslint-disable-next-line react-internal/safe-string-coercion
const currentValue = '' + (node[valueField]: any);
'' +
(// $FlowFixMe[prop-missing]
node[valueField]: any);
node._valueTracker = trackValueOnNode(node, valueField, expectedValue);
return currentValue !== expectedValue;
}

View File

@ -146,7 +146,7 @@ function createSyntheticEvent(Interface: EventInterfaceType) {
* @interface Event
* @see http://www.w3.org/TR/DOM-Level-3-Events/
*/
const EventInterface = {
const EventInterface: EventInterfaceType = {
eventPhase: 0,
bubbles: 0,
cancelable: 0,
@ -442,7 +442,7 @@ function getEventModifierState(nativeEvent: {[propName: string]: mixed}) {
* @interface KeyboardEvent
* @see http://www.w3.org/TR/DOM-Level-3-Events/
*/
const KeyboardEventInterface = {
const KeyboardEventInterface: EventInterfaceType = {
...UIEventInterface,
key: getEventKey,
code: 0,
@ -505,7 +505,7 @@ export const SyntheticKeyboardEvent: $FlowFixMe = createSyntheticEvent(
* @interface PointerEvent
* @see http://www.w3.org/TR/pointerevents/
*/
const PointerEventInterface = {
const PointerEventInterface: EventInterfaceType = {
...MouseEventInterface,
pointerId: 0,
width: 0,
@ -526,7 +526,7 @@ export const SyntheticPointerEvent: $FlowFixMe = createSyntheticEvent(
* @interface TouchEvent
* @see http://www.w3.org/TR/touch-events/
*/
const TouchEventInterface = {
const TouchEventInterface: EventInterfaceType = {
...UIEventInterface,
touches: 0,
targetTouches: 0,
@ -545,7 +545,7 @@ export const SyntheticTouchEvent: $FlowFixMe =
* @see http://www.w3.org/TR/2009/WD-css3-transitions-20090320/#transition-events-
* @see https://developer.mozilla.org/en-US/docs/Web/API/TransitionEvent
*/
const TransitionEventInterface = {
const TransitionEventInterface: EventInterfaceType = {
...EventInterface,
propertyName: 0,
elapsedTime: 0,
@ -559,7 +559,7 @@ export const SyntheticTransitionEvent: $FlowFixMe = createSyntheticEvent(
* @interface WheelEvent
* @see http://www.w3.org/TR/DOM-Level-3-Events/
*/
const WheelEventInterface = {
const WheelEventInterface: EventInterfaceType = {
...MouseEventInterface,
deltaX(event: {[propName: string]: mixed}) {
return 'deltaX' in event
@ -594,7 +594,7 @@ const WheelEventInterface = {
export const SyntheticWheelEvent: $FlowFixMe =
createSyntheticEvent(WheelEventInterface);
const ToggleEventInterface = {
const ToggleEventInterface: EventInterfaceType = {
...EventInterface,
newState: 0,
oldState: 0,

View File

@ -31,7 +31,7 @@ export type FormStatus = FormStatusPending | FormStatusNotPending;
// Since the "not pending" value is always the same, we can reuse the
// same object across all transitions.
const sharedNotPendingObject = {
const sharedNotPendingObject: FormStatusNotPending = {
pending: false,
data: null,
method: null,

View File

@ -207,6 +207,7 @@ const ResponderTouchHistoryStore = {
touchHistory.numberActiveTouches = nativeEvent.touches.length;
if (touchHistory.numberActiveTouches === 1) {
touchHistory.indexOfSingleActiveTouch =
// $FlowFixMe[incompatible-type] might be null according to type
nativeEvent.touches[0].identifier;
}
} else if (isEndish(topLevelType)) {

View File

@ -5020,7 +5020,7 @@ function commitPassiveUnmountInsideDeletedTreeOnFiber(
const instance: OffscreenInstance = offscreenFiber.stateNode;
const transitions = instance._transitions;
if (transitions !== null) {
const abortReason = {
const abortReason: TransitionAbort = {
reason: 'suspense',
name: current.memoizedProps.name || null,
};
@ -5061,7 +5061,7 @@ function commitPassiveUnmountInsideDeletedTreeOnFiber(
const instance: TracingMarkerInstance = current.stateNode;
const transitions = instance.transitions;
if (transitions !== null) {
const abortReason = {
const abortReason: TransitionAbort = {
reason: 'marker',
name: current.memoizedProps.name,
};

View File

@ -9,6 +9,7 @@
import type {Fiber, FiberRoot} from 'react-reconciler/src/ReactInternalTypes';
import type {
Container,
PublicInstance,
Instance,
TextInstance,
@ -505,7 +506,7 @@ function create(
isStrictMode = true;
}
}
let container = {
let container: Container = {
children: ([]: Array<Instance | TextInstance>),
createNodeMock,
tag: 'CONTAINER',

View File

@ -76,7 +76,7 @@ export function unstable_scheduleCallback<T>(
callback: SchedulerCallback<T>,
options?: {delay?: number},
): CallbackNode {
let postTaskPriority;
let postTaskPriority: PostTaskPriorityLevel;
switch (priorityLevel) {
case ImmediatePriority:
case UserBlockingPriority:

View File

@ -23,8 +23,7 @@ export function useSyncExternalStoreWithSelector<Snapshot, Selection>(
selector: (snapshot: Snapshot) => Selection,
isEqual?: (a: Selection, b: Selection) => boolean,
): Selection {
// Use this to track the rendered snapshot.
const instRef = useRef<
type Inst =
| {
hasValue: true,
value: Selection,
@ -32,10 +31,11 @@ export function useSyncExternalStoreWithSelector<Snapshot, Selection>(
| {
hasValue: false,
value: null,
}
| null,
>(null);
let inst;
};
// Use this to track the rendered snapshot.
const instRef = useRef<Inst | null>(null);
let inst: Inst;
if (instRef.current === null) {
inst = {
hasValue: false,

View File

@ -9298,12 +9298,12 @@ flatted@^3.2.9:
resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a"
integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==
flow-bin@^0.272:
version "0.272.2"
resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.272.2.tgz#918fc58dc7a99725a83314f453d3e49a56aebdc5"
integrity sha512-Rf8UG1biRBUGGh6qN7Ua2Y2lJRpR8Pbzby5kfHQ5m5SgjC5eOPw3Qjbrheb9ec5oU4L1gCOXRYbkbpr02PRUBw==
flow-bin@^0.273:
version "0.273.1"
resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.273.1.tgz#18621f169ecbabe3656c56980ebaabc439ee76c1"
integrity sha512-OlJkNCSd+i6z5xDoyGiS+3X5xYQx+vVUY2iUw6cHJR0LK3ttyA1wkiI93OuBALhLhF91KayzGhRSzXHqA75iUw==
flow-remove-types@^2.272:
flow-remove-types@^2.273:
version "2.279.0"
resolved "https://registry.yarnpkg.com/flow-remove-types/-/flow-remove-types-2.279.0.tgz#3a3388d9158eba0f82c40d80d31d9640b883a3f5"
integrity sha512-bPFloMR/A2b/r/sIsf7Ix0LaMicCJNjwhXc4xEEQVzJCIz5u7C7XDaEOXOiqveKlCYK7DcBNn6R01Cbbc9gsYA==