[change] Update Flow and types

This commit is contained in:
Nicolas Gallagher
2017-12-02 14:47:45 -08:00
parent 3e3cfc5325
commit 217ad97bfd
33 changed files with 135 additions and 75 deletions

View File

@@ -90,9 +90,9 @@
"eslint": "^4.6.1",
"eslint-config-prettier": "^2.6.0",
"eslint-plugin-promise": "^3.5.0",
"eslint-plugin-react": "^7.4.0",
"eslint-plugin-react": "^7.5.1",
"file-loader": "^1.1.4",
"flow-bin": "^0.49.1",
"flow-bin": "^0.60.1",
"jest": "^21.2.1",
"lint-staged": "^4.1.3",
"prettier": "^1.7.3",

View File

@@ -19,6 +19,7 @@ type Context = {
};
type Props = {
// $FlowFixMe
children?: React.Children,
rootTag: any
};
@@ -27,10 +28,7 @@ type State = {
mainKey: number
};
export default class AppContainer extends Component {
props: Props;
state: State = { mainKey: 1 };
export default class AppContainer extends Component<Props, State> {
static childContextTypes = {
rootTag: any
};

View File

@@ -13,16 +13,18 @@
import invariant from 'fbjs/lib/invariant';
import { unmountComponentAtNode } from 'react-dom';
import renderApplication, { getApplication } from './renderApplication';
import type { ComponentType } from 'react';
const emptyObject = {};
const runnables = {};
export type ComponentProvider = () => ReactClass<any>;
export type ComponentProvider = () => ComponentType<any>;
export type AppConfig = {
appKey: string,
component?: ComponentProvider,
run?: Function
run?: Function,
section?: boolean
};
/**
@@ -90,7 +92,7 @@ export default class AppRegistry {
runnables[appKey].run(appParameters);
}
static unmountApplicationComponentAtRootTag(rootTag) {
static unmountApplicationComponentAtRootTag(rootTag: Object) {
unmountComponentAtNode(rootTag);
}
}

View File

@@ -13,11 +13,11 @@ import invariant from 'fbjs/lib/invariant';
import { render } from 'react-dom';
import AppContainer from './AppContainer';
import StyleSheet from '../../apis/StyleSheet';
import React from 'react';
import React, { type ComponentType } from 'react';
export default function renderApplication(
RootComponent: ReactClass<Object>,
initialProps: Object,
export default function renderApplication<Props: Object>(
RootComponent: ComponentType<Props>,
initialProps: Props,
rootTag: any
) {
invariant(rootTag, 'Expect to have a valid rootTag, instead got ', rootTag);
@@ -30,7 +30,10 @@ export default function renderApplication(
);
}
export function getApplication(RootComponent: ReactClass<Object>, initialProps: Object): Object {
export function getApplication(
RootComponent: ComponentType<Object>,
initialProps: Object
): Object {
const element = (
<AppContainer rootTag={{}}>
<RootComponent {...initialProps} />

View File

@@ -20,7 +20,7 @@ const mergeLocalStorageItem = (key, value) => {
window.localStorage.setItem(key, nextValue);
};
const createPromise = (getValue, callback) => {
const createPromise = (getValue, callback): Promise<*> => {
return new Promise((resolve, reject) => {
try {
const value = getValue();
@@ -37,7 +37,7 @@ const createPromise = (getValue, callback) => {
});
};
const createPromiseAll = (promises, callback, processResult) => {
const createPromiseAll = (promises, callback, processResult): Promise<*> => {
return Promise.all(promises).then(
result => {
const value = processResult ? processResult(result) : null;
@@ -55,7 +55,7 @@ export default class AsyncStorage {
/**
* Erases *all* AsyncStorage for the domain.
*/
static clear(callback) {
static clear(callback?: Function): Promise<*> {
return createPromise(() => {
window.localStorage.clear();
}, callback);
@@ -69,7 +69,7 @@ export default class AsyncStorage {
/**
* Gets *all* keys known to the app, for all callers, libraries, etc.
*/
static getAllKeys(callback) {
static getAllKeys(callback?: Function): Promise<*> {
return createPromise(() => {
const numberOfKeys = window.localStorage.length;
const keys = [];
@@ -84,7 +84,7 @@ export default class AsyncStorage {
/**
* Fetches `key` value.
*/
static getItem(key: string, callback) {
static getItem(key: string, callback?: Function): Promise<*> {
return createPromise(() => {
return window.localStorage.getItem(key);
}, callback);
@@ -96,7 +96,7 @@ export default class AsyncStorage {
*
* multiGet(['k1', 'k2']) -> [['k1', 'val1'], ['k2', 'val2']]
*/
static multiGet(keys: Array<string>, callback) {
static multiGet(keys: Array<string>, callback?: Function): Promise<*> {
const promises = keys.map(key => AsyncStorage.getItem(key));
const processResult = result => result.map((value, i) => [keys[i], value]);
return createPromiseAll(promises, callback, processResult);
@@ -105,7 +105,7 @@ export default class AsyncStorage {
/**
* Sets `value` for `key`.
*/
static setItem(key: string, value: string, callback) {
static setItem(key: string, value: string, callback?: Function): Promise<*> {
return createPromise(() => {
window.localStorage.setItem(key, value);
}, callback);
@@ -115,7 +115,7 @@ export default class AsyncStorage {
* Takes an array of key-value array pairs.
* multiSet([['k1', 'val1'], ['k2', 'val2']])
*/
static multiSet(keyValuePairs: Array<Array<string>>, callback) {
static multiSet(keyValuePairs: Array<Array<string>>, callback?: Function): Promise<*> {
const promises = keyValuePairs.map(item => AsyncStorage.setItem(item[0], item[1]));
return createPromiseAll(promises, callback);
}
@@ -123,7 +123,7 @@ export default class AsyncStorage {
/**
* Merges existing value with input value, assuming they are stringified JSON.
*/
static mergeItem(key: string, value: string, callback) {
static mergeItem(key: string, value: string, callback?: Function): Promise<*> {
return createPromise(() => {
mergeLocalStorageItem(key, value);
}, callback);
@@ -135,7 +135,7 @@ export default class AsyncStorage {
*
* multiMerge([['k1', 'val1'], ['k2', 'val2']])
*/
static multiMerge(keyValuePairs: Array<Array<string>>, callback) {
static multiMerge(keyValuePairs: Array<Array<string>>, callback?: Function): Promise<*> {
const promises = keyValuePairs.map(item => AsyncStorage.mergeItem(item[0], item[1]));
return createPromiseAll(promises, callback);
}
@@ -143,7 +143,7 @@ export default class AsyncStorage {
/**
* Removes a `key`
*/
static removeItem(key: string, callback) {
static removeItem(key: string, callback?: Function): Promise<*> {
return createPromise(() => {
return window.localStorage.removeItem(key);
}, callback);
@@ -152,7 +152,7 @@ export default class AsyncStorage {
/**
* Delete all the keys in the `keys` array.
*/
static multiRemove(keys: Array<string>, callback) {
static multiRemove(keys: Array<string>, callback?: Function): Promise<*> {
const promises = keys.map(key => AsyncStorage.removeItem(key));
return createPromiseAll(promises, callback);
}

View File

@@ -17,11 +17,11 @@ export default class Clipboard {
);
}
static getString() {
static getString(): Promise<string> {
return Promise.resolve('');
}
static setString(text) {
static setString(text: string) {
let success = false;
const body = document.body;

View File

@@ -66,12 +66,12 @@ export default class Dimensions {
}
}
static addEventListener(type, handler): void {
static addEventListener(type: string, handler: Function): void {
listeners[type] = listeners[type] || [];
listeners[type].push(handler);
}
static removeEventListener(type, handler): void {
static removeEventListener(type: string, handler: Function): void {
if (Array.isArray(listeners[type])) {
listeners[type] = listeners[type].filter(_handler => _handler !== handler);
}

View File

@@ -17,13 +17,13 @@ const initialURL = canUseDOM ? window.location.href : '';
const Linking = {
addEventListener() {},
removeEventListener() {},
canOpenURL() {
canOpenURL(): Promise<boolean> {
return Promise.resolve(true);
},
getInitialURL() {
getInitialURL(): Promise<string> {
return Promise.resolve(initialURL);
},
openURL(url: string) {
openURL(url: string): Promise<Object | void> {
try {
iframeOpen(url);
return Promise.resolve();

View File

@@ -24,7 +24,7 @@ import { number, oneOf, string } from 'prop-types';
const ReactPropTypesSecret = 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED';
export default class StyleSheetValidation {
static validateStyleProp(prop, style, caller) {
static validateStyleProp(prop: string, style: Object, caller: string) {
if (process.env.NODE_ENV !== 'production') {
const isCustomProperty = prop.indexOf('--') === 0;
if (isCustomProperty) return;
@@ -51,7 +51,7 @@ export default class StyleSheetValidation {
}
}
static validateStyle(name, styles) {
static validateStyle(name: string, styles: Object) {
if (process.env.NODE_ENV !== 'production') {
for (const prop in styles[name]) {
StyleSheetValidation.validateStyleProp(prop, styles[name], 'StyleSheet ' + name);
@@ -59,7 +59,7 @@ export default class StyleSheetValidation {
}
}
static addValidStylePropTypes(stylePropTypes) {
static addValidStylePropTypes(stylePropTypes: Object) {
for (const key in stylePropTypes) {
allStylePropTypes[key] = stylePropTypes[key];
}

View File

@@ -21,7 +21,7 @@ const createSvgCircle = style => (
<circle cx="16" cy="16" fill="none" r="14" strokeWidth="4" style={style} />
);
class ActivityIndicator extends Component {
class ActivityIndicator extends Component<*> {
static displayName = 'ActivityIndicator';
static propTypes = {

View File

@@ -1,4 +1,5 @@
/* eslint-env jasmine, jest */
/* eslint-disable react/jsx-no-bind */
import React from 'react';
import Button from '..';

View File

@@ -17,7 +17,7 @@ import Text from '../Text';
import { bool, func, string } from 'prop-types';
import React, { Component } from 'react';
class Button extends Component {
class Button extends Component<*> {
static propTypes = {
accessibilityLabel: string,
color: ColorPropType,

View File

@@ -1,4 +1,5 @@
/* eslint-env jasmine, jest */
/* eslint-disable react/jsx-no-bind */
import Image from '../';
import ImageLoader from '../../../modules/ImageLoader';
@@ -120,7 +121,7 @@ describe('components/Image', () => {
const onLoadStub = jest.fn();
const uri = 'https://test.com/img.jpg';
const component = mount(<Image onLoad={onLoadStub} source={uri} />);
component.setProps({ source: `https://blah.com/img.png` });
component.setProps({ source: 'https://blah.com/img.png' });
jest.runOnlyPendingTimers();
expect(onLoadStub.mock.calls.length).toBe(2);
});

View File

@@ -83,9 +83,11 @@ const resolveAssetSource = source => {
return uri;
};
class Image extends Component {
state: { shouldDisplaySource: boolean };
type State = {
shouldDisplaySource: boolean
};
class Image extends Component<*, State> {
static displayName = 'Image';
static contextTypes = {

View File

@@ -17,7 +17,7 @@ import React, { Component } from 'react';
import type { ViewLayout, ViewLayoutEvent } from '../View/ViewPropTypes';
class KeyboardAvoidingView extends Component {
class KeyboardAvoidingView extends Component<*> {
static propTypes = {
...ViewPropTypes,
behavior: oneOf(['height', 'padding', 'position']),

View File

@@ -17,7 +17,7 @@ import ViewPropTypes from '../View/ViewPropTypes';
import React, { Component } from 'react';
import { bool, number } from 'prop-types';
class ProgressBar extends Component {
class ProgressBar extends Component<*> {
_progressElement: View;
static displayName = 'ProgressBar';

View File

@@ -16,7 +16,7 @@ import ViewPropTypes from '../View/ViewPropTypes';
import { arrayOf, bool, func, number, oneOf, string } from 'prop-types';
import React, { Component } from 'react';
class RefreshControl extends Component {
class RefreshControl extends Component<*> {
static propTypes = {
...ViewPropTypes,
colors: arrayOf(ColorPropType),

View File

@@ -48,7 +48,7 @@ const normalizeScrollEvent = e => ({
/**
* Encapsulates the Web-specific scroll throttling and disabling logic
*/
export default class ScrollViewBase extends Component {
export default class ScrollViewBase extends Component<*> {
_viewRef: View;
static propTypes = {
@@ -148,7 +148,7 @@ export default class ScrollViewBase extends Component {
};
};
_handleScroll = (e: SyntheticEvent) => {
_handleScroll = (e: Object) => {
e.persist();
e.stopPropagation();
const { scrollEventThrottle } = this.props;

View File

@@ -27,8 +27,14 @@ import { Children, Component } from 'react';
*
* Typically, you will not need to use this component and should opt for normal
* React reconciliation.
*/
export default class StaticContainer extends Component {
*/
type Props = {
children: any,
shouldUpdate: boolean
};
export default class StaticContainer extends Component<Props> {
static propTypes = {
children: any.isRequired,
shouldUpdate: bool.isRequired

View File

@@ -27,7 +27,12 @@ import { bool, func } from 'prop-types';
* React reconciliation.
*/
export default class StaticRenderer extends Component {
type Props = {
render: Function,
shouldUpdate: boolean
};
export default class StaticRenderer extends Component<Props> {
static propTypes = {
render: func.isRequired,
shouldUpdate: bool.isRequired

View File

@@ -11,7 +11,7 @@
import { Component } from 'react';
export default class StatusBar extends Component {
export default class StatusBar extends Component<*> {
static setBackgroundColor() {}
static setBarStyle() {}
static setHidden() {}

View File

@@ -11,14 +11,14 @@ import StyleSheet from '../../apis/StyleSheet';
import UIManager from '../../apis/UIManager';
import View from '../View';
import ViewPropTypes from '../View/ViewPropTypes';
import React, { PureComponent } from 'react';
import React, { Component } from 'react';
import { bool, func } from 'prop-types';
const emptyObject = {};
const thumbDefaultBoxShadow = '0px 1px 3px rgba(0,0,0,0.5)';
const thumbFocusedBoxShadow = `${thumbDefaultBoxShadow}, 0 0 0 10px rgba(0,0,0,0.1)`;
class Switch extends PureComponent {
class Switch extends Component<*> {
_checkboxElement: HTMLInputElement;
_thumbElement: View;

View File

@@ -1,4 +1,5 @@
/* eslint-env jasmine, jest */
/* eslint-disable react/jsx-no-bind */
import React from 'react';
import { render, shallow } from 'enzyme';

View File

@@ -18,7 +18,7 @@ import createElement from '../../modules/createElement';
import StyleSheet from '../../apis/StyleSheet';
import TextPropTypes from './TextPropTypes';
class Text extends Component {
class Text extends Component<*> {
static displayName = 'Text';
static propTypes = TextPropTypes;

View File

@@ -68,7 +68,7 @@ const setSelection = (node, selection) => {
} catch (e) {}
};
class TextInput extends Component {
class TextInput extends Component<*> {
_node: HTMLInputElement;
static displayName = 'TextInput';

View File

@@ -14,7 +14,7 @@ import BaseComponentPropTypes from '../../propTypes/BaseComponentPropTypes';
import createReactClass from 'create-react-class';
import EdgeInsetsPropType from '../../propTypes/EdgeInsetsPropType';
import ensurePositiveDelayProps from './ensurePositiveDelayProps';
import React from 'react';
import React, { type Element } from 'react';
import StyleSheet from '../../apis/StyleSheet';
import TimerMixin from 'react-timer-mixin';
import Touchable from './Touchable';
@@ -144,7 +144,7 @@ const TouchableWithoutFeedback = createReactClass({
return this.props.delayPressOut || 0;
},
render: function(): React.Element<any> {
render: function(): Element<any> {
const {
/* eslint-disable */
delayLongPress,

View File

@@ -17,7 +17,7 @@ import React, { Component } from 'react';
* Common implementation for a simple stubbed view.
*/
/* eslint-disable react/prop-types */
class UnimplementedView extends Component {
class UnimplementedView extends Component<*, *> {
setNativeProps() {
// Do nothing.
// This method is required in order to use this view as a Touchable* child.

View File

@@ -11,11 +11,13 @@
*/
import BaseComponentPropTypes from '../../propTypes/BaseComponentPropTypes';
import EdgeInsetsPropType from '../../propTypes/EdgeInsetsPropType';
import EdgeInsetsPropType, { type EdgeInsetsProp } from '../../propTypes/EdgeInsetsPropType';
import StyleSheetPropType from '../../propTypes/StyleSheetPropType';
import ViewStylePropTypes from './ViewStylePropTypes';
import { any, bool, func, oneOf } from 'prop-types';
const stylePropType = StyleSheetPropType(ViewStylePropTypes);
export type ViewLayout = {
x: number,
y: number,
@@ -29,6 +31,46 @@ export type ViewLayoutEvent = {
}
};
export type ViewProps = {
accessibilityComponentType?: string,
accessibilityLabel?: string,
accessibilityLiveRegion?: 'none' | 'polite' | 'assertive',
accessibilityRole?: string,
accessibilityTraits?: string | Array<string>,
accessible?: bool,
children?: any,
collapsable?: bool,
hitSlop?: EdgeInsetsProp,
importantForAccessibility?: 'auto'| 'yes'| 'no'| 'no-hide-descendants',
onAccessibilityTap?: Function,
onClick?: Function,
onClickCapture?: Function,
onLayout?: (event: ViewLayoutEvent) => void,
onMagicTap?: Function,
onResponderGrant?: Function,
onResponderMove?: Function,
onResponderReject?: Function,
onResponderRelease?: Function,
onResponderTerminate?: Function,
onResponderTerminationRequest?: Function,
onStartShouldSetResponder?: Function,
onStartShouldSetResponderCapture?: Function,
onMoveShouldSetResponder?: Function,
onMoveShouldSetResponderCapture?: Function,
onTouchCancel?: Function,
onTouchCancelCapture?: Function,
onTouchEnd?: Function,
onTouchEndCapture?: Function,
onTouchMove?: Function,
onTouchMoveCapture?: Function,
onTouchStart?: Function,
onTouchStartCapture?: Function,
pointerEvents?: 'box-none'| 'none'| 'box-only'| 'auto',
removeClippedSubviews?: boolean,
style?: stylePropType,
testID?: string,
}
const ViewPropTypes = {
...BaseComponentPropTypes,
children: any,
@@ -56,7 +98,7 @@ const ViewPropTypes = {
onTouchStart: func,
onTouchStartCapture: func,
pointerEvents: oneOf(['auto', 'box-none', 'box-only', 'none']),
style: StyleSheetPropType(ViewStylePropTypes)
style: stylePropType
};
export default ViewPropTypes;

View File

@@ -13,7 +13,7 @@ import { bool } from 'prop-types';
import createElement from '../../modules/createElement';
import invariant from 'fbjs/lib/invariant';
import StyleSheet from '../../apis/StyleSheet';
import ViewPropTypes from './ViewPropTypes';
import ViewPropTypes, { type ViewProps } from './ViewPropTypes';
import React, { Component } from 'react';
const calculateHitSlopStyle = hitSlop => {
@@ -27,7 +27,7 @@ const calculateHitSlopStyle = hitSlop => {
return hitStyle;
};
class View extends Component {
class View extends Component<ViewProps> {
static displayName = 'View';
static contextTypes = {
@@ -39,7 +39,6 @@ class View extends Component {
render() {
const {
hitSlop,
style,
/* eslint-disable */
collapsable,
onAccessibilityTap,
@@ -61,7 +60,7 @@ class View extends Component {
const { isInAParentText } = this.context;
otherProps.style = [styles.initial, isInAParentText && styles.inline, style];
otherProps.style = [styles.initial, isInAParentText && styles.inline, this.props.style];
if (hitSlop) {
const hitSlopStyle = calculateHitSlopStyle(hitSlop);

View File

@@ -5,7 +5,7 @@
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
* @noflow
*/
import { canUseDOM } from 'fbjs/lib/ExecutionEnvironment';
@@ -38,7 +38,7 @@ const safeOverride = (original, next) => {
return next;
};
const applyLayout = (Component: ReactClass<any>) => {
const applyLayout = (Component) => {
const componentDidMount = Component.prototype.componentDidMount;
const componentDidUpdate = Component.prototype.componentDidUpdate;
const componentWillUnmount = Component.prototype.componentWillUnmount;

View File

@@ -5,12 +5,12 @@
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
* @noflow
*/
import NativeMethodsMixin from '../NativeMethodsMixin';
const applyNativeMethods = (Component: ReactClass<any>) => {
const applyNativeMethods = (Component) => {
Object.keys(NativeMethodsMixin).forEach(method => {
if (!Component.prototype[method]) {
Component.prototype[method] = NativeMethodsMixin[method];

View File

@@ -7,7 +7,7 @@
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ColorPropType
* @flow
* @noflow
*/
const isWebColor = (color: string) =>

View File

@@ -1843,14 +1843,14 @@ eslint-plugin-promise@^3.5.0:
version "3.5.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-3.5.0.tgz#78fbb6ffe047201627569e85a6c5373af2a68fca"
eslint-plugin-react@^7.4.0:
version "7.4.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.4.0.tgz#300a95861b9729c087d362dd64abcc351a74364a"
eslint-plugin-react@^7.5.1:
version "7.5.1"
resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.5.1.tgz#52e56e8d80c810de158859ef07b880d2f56ee30b"
dependencies:
doctrine "^2.0.0"
has "^1.0.1"
jsx-ast-utils "^2.0.0"
prop-types "^15.5.10"
prop-types "^15.6.0"
eslint-scope@^3.7.1:
version "3.7.1"
@@ -2213,9 +2213,9 @@ flat-cache@^1.2.1:
graceful-fs "^4.1.2"
write "^0.2.1"
flow-bin@^0.49.1:
version "0.49.1"
resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.49.1.tgz#c9e456b3173a7535a4ffaf28956352c63bb8e3e9"
flow-bin@^0.60.1:
version "0.60.1"
resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.60.1.tgz#0f4fa7b49be2a916f18cd946fc4a51e32ffe4b48"
for-each@~0.3.2:
version "0.3.2"