Skip to content

Commit 769e734

Browse files
rubennortemeta-codesync[bot]
authored andcommitted
Make remaining Utilities modules Flow strict-local (#57739)
Summary: Pull Request resolved: #57739 Upgrade `deepDiffer`, `codegenNativeCommands`, `Dimensions`, and `ReactNativeTestTools` from `flow` to `flow strict-local`, preserving public type signatures. These operate on values of arbitrary shape, so the unavoidable internal `any` usages are marked with scoped `$FlowFixMe[unclear-type]`. Changelog: [Internal] Reviewed By: javache Differential Revision: D113763789
1 parent ed250e1 commit 769e734

8 files changed

Lines changed: 99 additions & 39 deletions

File tree

packages/react-native/Libraries/Utilities/Dimensions.js

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @flow
7+
* @flow strict-local
88
* @format
99
*/
1010

@@ -21,14 +21,39 @@ import invariant from 'invariant';
2121

2222
export type {DimensionsPayload, DisplayMetrics, DisplayMetricsAndroid};
2323

24+
export type DimensionsChangePayload = Readonly<{
25+
window: DisplayMetrics,
26+
screen: DisplayMetrics,
27+
}>;
28+
2429
/** @deprecated Use DisplayMetrics */
2530
export type ScaledSize = DisplayMetrics;
2631

2732
const eventEmitter = new EventEmitter<{
28-
change: [DimensionsPayload],
33+
change: [DimensionsChangePayload],
2934
}>();
3035
let dimensionsInitialized = false;
31-
let dimensions: DimensionsPayload;
36+
let dimensions: DimensionsChangePayload;
37+
38+
declare function addDimensionsEventListener(
39+
type: 'change',
40+
handler: (dimensions: DimensionsChangePayload) => void,
41+
): EventSubscription;
42+
declare function addDimensionsEventListener(
43+
type: 'change',
44+
handler: (dimensions: {window: {width: number, height: number}}) => void,
45+
): EventSubscription;
46+
function addDimensionsEventListener(
47+
type: 'change',
48+
handler: (dimensions: DimensionsChangePayload) => void,
49+
) {
50+
invariant(
51+
type === 'change',
52+
'Trying to subscribe to unknown event: "%s"',
53+
type,
54+
);
55+
return eventEmitter.addListener(type, handler);
56+
}
3257

3358
/**
3459
* Provides the application window's width and height. Prefer
@@ -91,6 +116,9 @@ class Dimensions {
91116
screen = window;
92117
}
93118

119+
invariant(window != null, 'Dimensions must define window metrics');
120+
invariant(screen != null, 'Dimensions must define screen metrics');
121+
94122
dimensions = {window, screen};
95123
if (dimensionsInitialized) {
96124
// Don't fire 'change' the first time the dimensions are set.
@@ -109,17 +137,8 @@ class Dimensions {
109137
* `screen` properties whose values are the same as the return values of
110138
* `Dimensions.get('window')` and `Dimensions.get('screen')`, respectively.
111139
*/
112-
static addEventListener(
113-
type: 'change',
114-
handler: Function,
115-
): EventSubscription {
116-
invariant(
117-
type === 'change',
118-
'Trying to subscribe to unknown event: "%s"',
119-
type,
120-
);
121-
return eventEmitter.addListener(type, handler);
122-
}
140+
static addEventListener: typeof addDimensionsEventListener =
141+
addDimensionsEventListener;
123142
}
124143

125144
// Subscribe before calling getConstants to make sure we don't miss any updates in between.

packages/react-native/Libraries/Utilities/ReactNativeTestTools.js

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @flow
7+
* @flow strict-local
88
* @format
99
*/
1010

@@ -163,7 +163,9 @@ function maximumDepthOfJSON(node: ?ReactTestRendererJSON): number {
163163
}
164164
}
165165

166-
function renderAndEnforceStrictMode(element: React.Node): any {
166+
function renderAndEnforceStrictMode(
167+
element: React.Node,
168+
): ReactTestRendererType {
167169
expectNoConsoleError();
168170
return renderWithStrictMode(element);
169171
}
@@ -217,8 +219,13 @@ function scrollToBottom(instance: ReactTestInstance) {
217219
// To make error messages a little bit better, we attach a custom toString
218220
// implementation to a predicate
219221
function withMessage(fn: Predicate, message: string): Predicate {
220-
(fn as any).toString = () => message;
221-
return fn;
222+
return new Proxy(fn, {
223+
get(target, property, receiver) {
224+
return property === 'toString'
225+
? () => message
226+
: Reflect.get(target, property, receiver);
227+
},
228+
});
222229
}
223230

224231
export {byClickable};

packages/react-native/Libraries/Utilities/codegenNativeCommands.js

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,30 +4,40 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @flow
7+
* @flow strict-local
88
* @format
99
*/
1010

11+
import type {HostInstance} from '../../src/private/types/HostInstance';
12+
1113
const {dispatchCommand} = require('../ReactNative/RendererProxy');
1214

1315
type NativeCommandsOptions<T = string> = Readonly<{
1416
supportedCommands: ReadonlyArray<T>,
1517
}>;
1618

19+
declare function castCommandObject<T extends interface {}>(commandObj: {
20+
[keyof T]: (...ReadonlyArray<unknown>) => void,
21+
}): T;
22+
function castCommandObject(commandObj: interface {}) {
23+
return commandObj;
24+
}
25+
1726
function codegenNativeCommands<T extends interface {}>(
18-
options: NativeCommandsOptions<keyof T>,
27+
options: NativeCommandsOptions<keyof T & string>,
1928
): T {
2029
const commandObj: {[keyof T]: (...ReadonlyArray<unknown>) => void} = {};
2130

2231
options.supportedCommands.forEach(command => {
23-
// $FlowFixMe[missing-local-annot]
24-
commandObj[command] = (ref, ...args) => {
25-
// $FlowFixMe[incompatible-type]
32+
commandObj[command] = (
33+
ref: HostInstance,
34+
...args: Array<unknown>
35+
): void => {
2636
dispatchCommand(ref, command, args);
2737
};
2838
});
2939

30-
return commandObj as any as T;
40+
return castCommandObject(commandObj);
3141
}
3242

3343
export default codegenNativeCommands;

packages/react-native/Libraries/Utilities/differ/__tests__/deepDiffer-itest.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ describe('deepDiffer', function () {
136136
expect(
137137
deepDiffer(
138138
() => {},
139-
x => x,
139+
(x: unknown) => x,
140140
),
141141
).toBe(false);
142142
const f = () => {};
@@ -146,7 +146,7 @@ describe('deepDiffer', function () {
146146
expect(
147147
deepDiffer(
148148
() => {},
149-
x => x,
149+
(x: unknown) => x,
150150
undefined,
151151
{unsafelyIgnoreFunctions: false},
152152
),
@@ -160,7 +160,7 @@ describe('deepDiffer', function () {
160160
expect(
161161
deepDiffer(
162162
() => {},
163-
x => x,
163+
(x: unknown) => x,
164164
{unsafelyIgnoreFunctions: false},
165165
),
166166
).toBe(true);

packages/react-native/Libraries/Utilities/differ/deepDiffer.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @flow
7+
* @flow strict-local
88
* @format
99
*/
1010

@@ -29,8 +29,8 @@ function unstable_setLogListeners(listeners: ?LogListeners) {
2929
* @returns {bool} true if different, false if equal
3030
*/
3131
function deepDiffer(
32-
one: any,
33-
two: any,
32+
one: unknown,
33+
two: unknown,
3434
maxDepthOrOptions: Options | number = -1,
3535
maybeOptions?: Options,
3636
): boolean {
@@ -73,7 +73,9 @@ function deepDiffer(
7373
return true;
7474
}
7575
if (Array.isArray(one)) {
76-
// We know two is also an array because the constructors are equal
76+
if (!Array.isArray(two)) {
77+
return true;
78+
}
7779
const len = one.length;
7880
if (two.length !== len) {
7981
return true;

packages/react-native/Libraries/Utilities/useWindowDimensions.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,10 @@ export default function useWindowDimensions():
2727
useEffect(() => {
2828
function handleChange({
2929
window,
30-
}: {
30+
}: Readonly<{
3131
window: DisplayMetrics | DisplayMetricsAndroid,
32-
}) {
32+
...
33+
}>) {
3334
if (
3435
dimensions.width !== window.width ||
3536
dimensions.height !== window.height ||

packages/react-native/ReactNativeApi.d.ts

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<efd59db9214ec5f9de127d9b01190bc6>>
7+
* @generated SignedSource<<0a4f0d7eaba8d41ac162fef49584255e>>
88
*
99
* This file was generated by scripts/js-api/build-types/index.js.
1010
*/
@@ -1116,6 +1116,23 @@ declare type add = typeof add
11161116
declare function addChangeListener(
11171117
listener: (preferences: AppearancePreferences) => void,
11181118
): EventSubscription
1119+
declare function addDimensionsEventListener(
1120+
type: "change",
1121+
handler: (dimensions: DimensionsChangePayload) => void,
1122+
): EventSubscription
1123+
declare function addDimensionsEventListener(
1124+
type: "change",
1125+
handler: (dimensions: {
1126+
window: {
1127+
height: number
1128+
width: number
1129+
}
1130+
}) => void,
1131+
): EventSubscription
1132+
declare function addDimensionsEventListener(
1133+
type: "change",
1134+
handler: (dimensions: DimensionsChangePayload) => void,
1135+
): void
11191136
declare class Alert {
11201137
static alert(
11211138
title: null | string | undefined,
@@ -1730,7 +1747,7 @@ declare class CellRenderMask {
17301747
declare type Clipboard = typeof Clipboard
17311748
declare type codegenNativeCommands = typeof codegenNativeCommands
17321749
declare function codegenNativeCommands_default<T extends {}>(
1733-
options: NativeCommandsOptions<keyof T>,
1750+
options: NativeCommandsOptions<keyof T & string>,
17341751
): T
17351752
declare type codegenNativeComponent = typeof codegenNativeComponent
17361753
declare function codegenNativeComponent_default<Props extends {}>(
@@ -1879,10 +1896,14 @@ declare type DevMenuStatic = {
18791896
declare type DevSettings = typeof DevSettings
18801897
declare type diffClamp = typeof diffClamp
18811898
declare class Dimensions {
1882-
static addEventListener(type: "change", handler: Function): EventSubscription
1899+
static addEventListener: typeof addDimensionsEventListener
18831900
static get(dim: string): DisplayMetrics | DisplayMetricsAndroid
18841901
static set(dims: Readonly<DimensionsPayload>): void
18851902
}
1903+
declare type DimensionsChangePayload = {
1904+
readonly screen: DisplayMetrics
1905+
readonly window: DisplayMetrics
1906+
}
18861907
declare type DimensionsPayload = {
18871908
screen?: DisplayMetrics
18881909
screenPhysicalPixels?: DisplayMetricsAndroid
@@ -5797,7 +5818,7 @@ export {
57975818
DeviceInfo, // 0f5a517b
57985819
DeviceInfoConstants, // 279e7858
57995820
DimensionValue, // b163a381
5800-
Dimensions, // 980ef68c
5821+
Dimensions, // 7439fe08
58015822
DimensionsPayload, // 653bc26c
58025823
DisplayMetrics, // 1dc35cef
58035824
DisplayMetricsAndroid, // 872e62eb
@@ -6051,7 +6072,7 @@ export {
60516072
VirtualizedSectionListInstance, // 12b706d5
60526073
VirtualizedSectionListProps, // 52c34787
60536074
WrapperComponentProvider, // 9b4247f6
6054-
codegenNativeCommands, // 628a7c0a
6075+
codegenNativeCommands, // 322f3f4e
60556076
codegenNativeComponent, // 520daa94
60566077
findNodeHandle, // 93f80214
60576078
processColor, // 6e877698

packages/rn-tester/js/examples/Dimensions/DimensionsExample.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import * as React from 'react';
1515
import {useEffect, useState} from 'react';
1616
import {Button, Dimensions, View, useWindowDimensions} from 'react-native';
1717

18-
type Props = {dim: string};
18+
type Props = {dim: 'screen' | 'window'};
1919

2020
function DimensionsSubscription(props: Props) {
2121
const [dims, setDims] = useState(() => Dimensions.get(props.dim));

0 commit comments

Comments
 (0)