Typescript слияние стилизованных реквизитов компонентов с родительскими реквизитами

#reactjs #typescript #styled-components

#reactjs #typescript #styled-компоненты

Вопрос:

У меня есть стилизованный компонент, который выглядит следующим образом:

 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};
`;
 

Он заключен в другой компонент:

 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>
  );
};
 

Если я добавлю StyledComponent<"div", any, BoxProps, never> к React.FC<ContainerProps> :

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

распространение реквизитов выдаст мне следующую ошибку:
Rest types may only be created from object types
Я пытался React.HTMLAttributes<{}> amp; typeof Box.propTypes и React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement> безуспешно…

Есть ли способ объединить стилизованный реквизит компонента с родительским реквизитом?

Спасибо!

Ответ №1:

styled.div просто визуализируйте a div , и он принимает любые свойства div , которые будут принимать ваши свойства от BoxProps . Вы можете получить тип, который описывает свойства элемента JSX, используя React.HTMLAttributes<HTMLElementYouNeed> в этом случае React.HTMLAttributes<HTMLDivElement> , поэтому реквизит Box теперь будет этим плюсом BoxProps :

 React.FC<ContainerProps amp; React.HTMLAttributes<HTMLDivElement> amp; BoxProps>
 

Если вам лень это писать, вы можете создать пространство имен утилиты в каком-нибудь файле вашего проекта:

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

Затем импортируйте это и используйте

 React.FC<ContainerProps amp; HTMLProps.div amp; BoxProps>
 

Ответ №2:

Ответ Алекса верен, но в некоторых случаях он не будет работать. Например, у меня был этот стилизованный компонент:

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

использование:

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

выдает ошибку в родительском компоненте.

для этого вам нужно:

 Omit<React.ComponentPropsWithoutRef<'input'>, 'type'>