Search code examples
typescriptreact-native

RN - typescript style as a prop


I'm gradually moving a RN project to typescript. I have a question about declaring types for styles that are being passed as a props to a component.

The Props within the component are defined as follows:

interface Props {
  children: ReactNode;
  style?: ViewStyle;
}

It's ok if I pass just a simple styles object, eg:

<Component style={{ marginTop: 1 }}>...children...</Component>
<Component style={styleObj}>....children...</Component>

But it fails if I pass an array of styles:

<Component style={[styleObj, { marginTop: someVar }]}>...children...</Component>

What would be the best way to specify the style prop type?

EDIT: and the TS message is:

TS2559: Type '({ flex: number; } | { marginTop: number; })[]' has no properties in common with type 'ViewStyle'.  Component.tsx(12, 3): The expected type comes from property 'style' which is declared here on type 'IntrinsicAttributes & Props'

Solution

  • If you have control over the style propType, change it to:

    interface Props {
      children: ReactNode;
      style?: StyleProp<ViewStyle>;
    }
    

    Further discussion

    Sometimes when I find myself reusing the props of my base component, I like to extend the prop type with that of the base component to save myself the trouble of having to figure out what type I need.

    Example

    This isn't the most exhaustive example, but it should demonstrate the main purpose of this pattern. I hope you find this of use.

    I have a custom component called CustomView, which at its core, is just a react-native View component. I can then extend CustomView's prop type with that of View.

    interface Props extends React.ComponentProps<typeof View> {
       customPropsOne: string;
       // also contains all props of the View component
    }
    
    const CustomView = (props: Props) => {
       // make use of the ...rest operator to extract the extended View props
       const {customPropsOne, ...rest} = props;
    
       return(
          <View {...rest}>
             <Text>
                {customPropsOne}
             </Text>
          </View>
       )
    }
    
    // example component usage
    
    <CustomView
       style={[myStyles, anotherStyle]}
       accessibilityLabel={"main view"}>
       {children}
    </CustomView>