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.
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.
Share Improve this question edited Feb 11, 2019 at 17:00 chazsolo 8,4391 gold badge23 silver badges45 bronze badges asked Feb 11, 2019 at 16:50 Robbie MilejczakRobbie Milejczak 5,7703 gold badges35 silver badges68 bronze badges2 Answers
Reset to default 13As 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,
])}
You need a type like this:
import { ViewStyle, StyleProp } from 'react-native';
type Props = {
style?: StyleProp<ViewStyle>;
};
If the element is Text use TextStyle
type.