Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typescript merging styled component props with the parent ones

I have a styled component that look like this:

interface BoxProps {
    color?: string;
    backgroundColor?: string;
    borderColor?: string;
  }

export const Box = styled.div<BoxProps>`
  position: relative;
  padding: 0.75rem 1.25rem;
  margin-bottom: 1rem;
  border: 1px solid transparent;
  border-radius: 0.25rem;
  text-align: left;
  color: ${(props) => props.color};
  background-color: ${(props) => props.backgroundColor};
  border-color: ${(props) => props.borderColor};
`;

It's wrapped in another component:

export const Container: React.FC<ContainerProps> = ({
  variant,
  children,
  ...props
}) => {
  const { color, backgroundColor, borderColor } = variantColor(variant);

  return (
    <div>
      <Box
        color={color}
        backgroundColor={backgroundColor}
        borderColor={borderColor}
        {...props}
      >
        {children}
      </Box>
      <p></p>
      // ...
    </div>
  );
};

If I add StyledComponent<"div", any, BoxProps, never> to React.FC<ContainerProps>:

React.FC<ContainerProps & StyledComponent<"div", any, BoxProps, never>>

spreading props will give me the following error: Rest types may only be created from object types I tried React.HTMLAttributes<{}> & typeof Box.propTypes and React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement> without luck...

Is there a way to merge a styled-component props with the parent props?

Thanks!

like image 586
sh4rp3r Avatar asked Oct 20 '25 17:10

sh4rp3r


2 Answers

styled.div just renders a div and it accepts any properties div would accept + your properties from BoxProps. You can get a type that described properties of a JSX element using React.HTMLAttributes<HTMLElementYouNeed> in this case React.HTMLAttributes<HTMLDivElement>, so props of Box would now be this plus BoxProps:

React.FC<ContainerProps & React.HTMLAttributes<HTMLDivElement> & BoxProps>

If you are too lazy to write this, you could make a utility namespace in some file in your project:

declare namespace HTMLProps {
  type div = React.HTMLAttributes<HTMLDivProps>
  // Maybe define props for other html elements if you need
}
export default HTMLProps

Then import this and use

React.FC<ContainerProps & HTMLProps.div & BoxProps>
like image 79
Alex Chashin Avatar answered Oct 23 '25 07:10

Alex Chashin


Alex's answer is valid but in some cases it won't work. For instance I had this styled component:

export const CustomInput = styled.input.attrs({ type: 'text' })``;

using:

React.HTMLAttributes<HTMLInputElement>
// or
Omit<React.HTMLAttributes<HTMLInputElement>,'type'>

gives an error in the parent component.

for this to work you need:

Omit<React.ComponentPropsWithoutRef<'input'>, 'type'>
like image 45
sh4rp3r Avatar answered Oct 23 '25 05:10

sh4rp3r



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!