In React Native, view elements accept a style
property that uses CSS property names in a camel cased object:
const styleObj = {
width: 200,
marginTop: 10
}
Elements also accept an array of style objects like this:
<MyComponent style={[ styleObj, styleProp && styleProp ]} />
I have several abstracted button components that rely on a shared base button interface. For simplicities sake:
interface IButton {
style?: ViewStyle | ViewStyle[] // <-- ViewStyle is exported by react native, and contains all the allowed style properties for a View component
}
I thought this definition would be adequate, but I'm running into some issues that I'm having difficulty understanding.
I have a DropDown
component which renders a Button
. When I use the style prop I get an error:
<Button
style={[
{
backgroundColor: backgroundColor || COLORS.lightRed,
borderRadius: 3,
height: 44,
width: '100%',
},
style && style, // <-- type is ViewStyle | ViewStyle[], this is passed in as a prop
]}
The above throws the error:
Type (ViewStyle | ViewStyle[] | undefined)[] is not assignable to ViewStyle | ViewStyle[] | undefined
If I cast style: style && (style as ViewStyle)
I get a different error:
Type (ViewStyle | undefined)[] is not assignable to ViewStyle[]
If I cast the entire array is a ViewStyle
the error clears:
<Button
style={[
{
backgroundColor: backgroundColor || COLORS.lightRed,
borderRadius: 3,
height: 44,
width: '100%',
},
style && style,
] as ViewStyle}
Which is fine but I'm a bit confused. I have a hunch that, since my components are using the same props interface, TypeScript is getting confused. Ultimately I'm unsure why those errors are happening, and what is incorrect about my definition that I need to rely on casting.
As obvious as this should have been, it took me a while to find the best solution.
When typing your style props, use ViewStyle
, TextStyle
etc (instead of StyleProp<T>
), and when passing an array of styles simply use Stylesheet.flatten()
to silence any type incompatibilities:
<Button
style={Stylesheet.flatten([
{
backgroundColor: backgroundColor || COLORS.lightRed,
borderRadius: 3,
height: 44,
width: '100%',
},
style && style,
])}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With