Skip to content

Commit da04796

Browse files
nmnfacebook-github-bot
authored andcommitted
Improve types for React Native styles.
Reviewed By: TheSavior Differential Revision: D6226807 fbshipit-source-id: b64a77383e6e685f4017c47fc9a5095ed63b062c
1 parent 3e4cf0e commit da04796

File tree

3 files changed

+255
-10
lines changed

3 files changed

+255
-10
lines changed

Libraries/Inspector/ElementProperties.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,11 @@ const flattenStyle = require('flattenStyle');
2525
const mapWithSeparator = require('mapWithSeparator');
2626
const openFileInEditor = require('openFileInEditor');
2727

28+
import type {StyleObj} from 'StyleSheetTypes';
29+
2830
class ElementProperties extends React.Component<{
2931
hierarchy: Array<$FlowFixMe>,
30-
style?: Object | Array<$FlowFixMe> | number,
32+
style?: StyleObj,
3133
source?: {
3234
fileName?: string,
3335
lineNumber?: number,

Libraries/StyleSheet/StyleSheet.js

+17-7
Original file line numberDiff line numberDiff line change
@@ -18,24 +18,34 @@ const StyleSheetValidation = require('StyleSheetValidation');
1818

1919
const flatten = require('flattenStyle');
2020

21-
export type Styles = {[key: string]: Object};
22-
export type StyleSheet<S: Styles> = {[key: $Keys<S>]: number};
23-
export type StyleValue = Object | number | false | null | void | '';
24-
export type StyleProp = StyleValue | Array<StyleProp>;
21+
import type {
22+
StyleSheetStyle as _StyleSheetStyle,
23+
Styles as _Styles,
24+
StyleSheet as _StyleSheet,
25+
StyleValue as _StyleValue,
26+
StyleObj,
27+
} from 'StyleSheetTypes';
28+
29+
export type StyleProp = StyleObj;
30+
export type Styles = _Styles;
31+
export type StyleSheet<S> = _StyleSheet<S>;
32+
export type StyleValue = _StyleValue;
33+
export type StyleSheetStyle = _StyleSheetStyle;
2534

2635
let hairlineWidth = PixelRatio.roundToNearestPixel(0.4);
2736
if (hairlineWidth === 0) {
2837
hairlineWidth = 1 / PixelRatio.get();
2938
}
3039

3140
const absoluteFillObject = {
32-
position: 'absolute',
41+
position: ('absolute': 'absolute'),
3342
left: 0,
3443
right: 0,
3544
top: 0,
3645
bottom: 0,
3746
};
38-
const absoluteFill = ReactNativePropRegistry.register(absoluteFillObject); // This also freezes it
47+
const absoluteFill: typeof absoluteFillObject =
48+
ReactNativePropRegistry.register(absoluteFillObject); // This also freezes it
3949

4050
/**
4151
* A StyleSheet is an abstraction similar to CSS StyleSheets
@@ -197,7 +207,7 @@ module.exports = {
197207
* Creates a StyleSheet style reference from the given object.
198208
*/
199209
create<S: Styles>(obj: S): StyleSheet<S> {
200-
const result: StyleSheet<S> = {};
210+
const result = {};
201211
for (const key in obj) {
202212
StyleSheetValidation.validateStyle(key, obj);
203213
result[key] = obj[key] && ReactNativePropRegistry.register(obj[key]);

Libraries/StyleSheet/StyleSheetTypes.js

+235-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,241 @@
88
*
99
* @providesModule StyleSheetTypes
1010
* @flow
11+
* @format
1112
*/
13+
1214
'use strict';
1315

14-
type Atom = number | bool | Object | Array<?Atom>;
15-
export type StyleObj = Atom;
16+
import AnimatedNode from 'AnimatedNode';
17+
18+
export opaque type StyleSheetStyle: number = number;
19+
20+
export type ColorValue = null | string;
21+
export type DimensionValue = null | number | string | AnimatedNode;
22+
23+
export type LayoutStyle<+Dimension = DimensionValue> = {
24+
+display?: 'none' | 'flex',
25+
+width?: Dimension,
26+
+height?: Dimension,
27+
+top?: Dimension,
28+
+bottom?: Dimension,
29+
+left?: Dimension,
30+
+right?: Dimension,
31+
+minWidth?: Dimension,
32+
+maxWidth?: Dimension,
33+
+minHeight?: Dimension,
34+
+maxHeight?: Dimension,
35+
+margin?: Dimension,
36+
+marginVertical?: Dimension,
37+
+marginHorizontal?: Dimension,
38+
+marginTop?: Dimension,
39+
+marginBottom?: Dimension,
40+
+marginLeft?: Dimension,
41+
+marginRight?: Dimension,
42+
+padding?: Dimension,
43+
+paddingVertical?: Dimension,
44+
+paddingHorizontal?: Dimension,
45+
+paddingTop?: Dimension,
46+
+paddingBottom?: Dimension,
47+
+paddingLeft?: Dimension,
48+
+paddingRight?: Dimension,
49+
+borderWidth?: number,
50+
+borderTopWidth?: number,
51+
+borderBottomWidth?: number,
52+
+borderLeftWidth?: number,
53+
+borderRightWidth?: number,
54+
+position?: 'absolute' | 'relative',
55+
+flexDirection?: 'row' | 'row-reverse' | 'column' | 'column-reverse',
56+
+flexWrap?: 'wrap' | 'nowrap',
57+
+justifyContent?:
58+
| 'flex-start'
59+
| 'flex-end'
60+
| 'center'
61+
| 'space-between'
62+
| 'space-around',
63+
+alignItems?: 'flex-start' | 'flex-end' | 'center' | 'stretch' | 'baseline',
64+
+alignSelf?:
65+
| 'auto'
66+
| 'flex-start'
67+
| 'flex-end'
68+
| 'center'
69+
| 'stretch'
70+
| 'baseline',
71+
+alignContent?:
72+
| 'flex-start'
73+
| 'flex-end'
74+
| 'center'
75+
| 'stretch'
76+
| 'space-between'
77+
| 'space-around',
78+
+overflow?: 'visible' | 'hidden' | 'scroll',
79+
+flex?: number,
80+
+flexGrow?: number,
81+
+flexShrink?: number,
82+
+flexBasis?: number | string,
83+
+aspectRatio?: number,
84+
+zIndex?: number,
85+
+direction?: 'inherit' | 'ltr' | 'rtl',
86+
};
87+
88+
export type TransformStyle = {
89+
+transform?: $ReadOnlyArray<
90+
| {+perspective: number | AnimatedNode}
91+
| {+rotate: string}
92+
| {+rotateX: string}
93+
| {+rotateY: string}
94+
| {+rotateZ: string}
95+
| {+scale: number | AnimatedNode}
96+
| {+scaleX: number | AnimatedNode}
97+
| {+scaleY: number | AnimatedNode}
98+
| {+translateX: number | AnimatedNode}
99+
| {+translateY: number | AnimatedNode}
100+
| {
101+
+translate: [number | AnimatedNode, number | AnimatedNode] | AnimatedNode,
102+
}
103+
| {+skewX: string}
104+
| {+skewY: string}
105+
// TODO: what is the actual type it expects?
106+
| {+matrix: $ReadOnlyArray<number | AnimatedNode> | AnimatedNode},
107+
>,
108+
};
109+
110+
export type ShadowStyle<+Color = ColorValue> = {
111+
+shadowColor?: Color,
112+
+shadowOffset?: {
113+
+width?: number,
114+
+height?: number,
115+
},
116+
+shadowOpacity?: number | AnimatedNode,
117+
+shadowRadius?: number,
118+
};
119+
120+
export type ViewStyle<+Dimension = DimensionValue, +Color = ColorValue> = {
121+
...$Exact<LayoutStyle<Dimension>>,
122+
...$Exact<ShadowStyle<Color>>,
123+
...$Exact<TransformStyle>,
124+
+backfaceVisibility?: 'visible' | 'hidden',
125+
+backgroundColor?: Color,
126+
+borderColor?: Color,
127+
+borderTopColor?: Color,
128+
+borderRightColor?: Color,
129+
+borderBottomColor?: Color,
130+
+borderLeftColor?: Color,
131+
+borderRadius?: number,
132+
+borderTopLeftRadius?: number,
133+
+borderTopRightRadius?: number,
134+
+borderBottomLeftRadius?: number,
135+
+borderBottomRightRadius?: number,
136+
+borderStyle?: 'solid' | 'dotted' | 'dashed',
137+
+borderWidth?: number,
138+
+borderTopWidth?: number,
139+
+borderRightWidth?: number,
140+
+borderBottomWidth?: number,
141+
+borderLeftWidth?: number,
142+
+opacity?: number | AnimatedNode,
143+
+elevation?: number,
144+
};
145+
146+
export type TextStyle<+Dimension = DimensionValue, +Color = ColorValue> = {
147+
...$Exact<ViewStyle<Dimension, Color>>,
148+
+color?: Color,
149+
+fontFamily?: string,
150+
+fontSize?: number,
151+
+fontStyle?: 'normal' | 'italic',
152+
+fontWeight?:
153+
| 'normal'
154+
| 'bold'
155+
| '100'
156+
| '200'
157+
| '300'
158+
| '400'
159+
| '500'
160+
| '600'
161+
| '700'
162+
| '800'
163+
| '900',
164+
+fontVariant?: $ReadOnlyArray<
165+
| 'small-caps'
166+
| 'oldstyle-nums'
167+
| 'lining-nums'
168+
| 'tabular-nums'
169+
| 'proportional-nums',
170+
>,
171+
+textShadowOffset?: {+width?: number, +height?: number},
172+
+textShadowRadius?: number,
173+
+textShadowColor?: Color,
174+
+letterSpacing?: number,
175+
+lineHeight?: number,
176+
+textAlign?: 'auto' | 'left' | 'right' | 'center' | 'justify',
177+
+textAlignVertical?: 'auto' | 'top' | 'bottom' | 'center',
178+
+includeFontPadding?: boolean,
179+
+textDecorationLine?:
180+
| 'none'
181+
| 'underline'
182+
| 'line-through'
183+
| 'underline line-through',
184+
+textDecorationStyle?: 'solid' | 'double' | 'dotted' | 'dashed',
185+
+textDecorationColor?: Color,
186+
+writingDirection?: 'auto' | 'ltr' | 'rtl',
187+
};
188+
189+
export type ImageStyle<+Dimension = DimensionValue, +Color = ColorValue> = {
190+
...$Exact<ViewStyle<Dimension, Color>>,
191+
+resizeMode?: 'contain' | 'cover' | 'stretch' | 'center' | 'repeat',
192+
+tintColor?: Color,
193+
+overlayColor?: string,
194+
};
195+
196+
export type Style<+Dimension = DimensionValue, +Color = ColorValue> = {
197+
...$Exact<TextStyle<Dimension, Color>>,
198+
+resizeMode?: 'contain' | 'cover' | 'stretch' | 'center' | 'repeat',
199+
+tintColor?: Color,
200+
+overlayColor?: string,
201+
};
202+
203+
export type StyleProp<+T> =
204+
| null
205+
| void
206+
| T
207+
| StyleSheetStyle
208+
| number
209+
| false
210+
| ''
211+
| $ReadOnlyArray<StyleProp<T>>;
212+
213+
// export type ViewStyleProp = StyleProp<$Shape<ViewStyle<DimensionValue>>>;
214+
// export type TextStyleProp = StyleProp<
215+
// $Shape<TextStyle<DimensionValue, ColorValue>>,
216+
// >;
217+
// export type ImageStyleProp = StyleProp<
218+
// $Shape<ImageStyle<DimensionValue, ColorValue>>,
219+
// >;
220+
221+
export type StyleObj = StyleProp<$Shape<Style<DimensionValue, ColorValue>>>;
222+
export type StyleValue = StyleObj;
223+
224+
export type ViewStyleProp = StyleObj;
225+
export type TextStyleProp = StyleObj;
226+
export type ImageStyleProp = StyleObj;
227+
228+
export type Styles = {
229+
+[key: string]: $Shape<Style<DimensionValue, ColorValue>>,
230+
};
231+
export type StyleSheet<+S: Styles> = $ObjMap<S, (Object) => StyleSheetStyle>;
232+
233+
/*
234+
Utility type get non-nullable types for specific style keys.
235+
Useful when a component requires values for certain Style Keys.
236+
So Instead:
237+
```
238+
type Props = {position: string};
239+
```
240+
You should use:
241+
```
242+
type Props = {position: TypeForStyleKey<'position'>};
243+
```
244+
245+
This will correctly give you the type 'absolute' | 'relative' instead of the
246+
weak type of just string;
247+
*/
248+
export type TypeForStyleKey<+key: $Keys<Style<>>> = $ElementType<Style<>, key>;

0 commit comments

Comments
 (0)