web-dev-qa-db-fra.com

Utilisation de composants stylisés "en tant que" accessoire avec dactylographié

Je suis en train de construire une bibliothèque de modèles dans laquelle j'ai construit un composant Button en utilisant React et styled-components. Basé sur le composant Button, je veux que tous mes composants Links soient exactement les mêmes et reçoivent exactement les mêmes accessoires. À cette fin, j'utilise le support as de styled-components, ce qui me permet d'utiliser cet élément déjà construit comme autre balise ou composant.

Composant du bouton

import * as React from 'react'
import { ButtonBorderAnimation } from './ButtonAnimation'
import { ButtonProps, ButtonVariant } from './Button.types'
import { ButtonBase, LeftIcon, RightIcon } from './Button.styled'

function Button({
  variant = ButtonVariant.Filled,
  children,
  leftIcon = null,
  rightIcon = null,
  ...props
}: ButtonProps): JSX.Element {
  return (
    <ButtonBase variant={variant} {...props}>
      {variant !== ButtonVariant.Ghost ? (
        <ButtonBorderAnimation {...props} />
      ) : null}
      {leftIcon ? <LeftIcon>{leftIcon}</LeftIcon> : null}
      {children}
      {rightIcon ? <RightIcon>{rightIcon}</RightIcon> : null}
    </ButtonBase>
  )
}

export default Button

Types de boutons

export interface ButtonProps {
  children: React.ReactNode
  variant?: 'filled' | 'outlined' | 'ghost'
  size?: 'small' | 'regular'
  underlinedOnHover?: boolean
  leftIcon?: React.ReactNode
  rightIcon?: React.ReactNode
  inverse?: boolean
}

export enum ButtonVariant {
  Filled = 'filled',
  Outlined = 'outlined',
  Ghost = 'ghost',
}

export enum ButtonSize {
  Small = 'small',
  Regular = 'regular',
}

Composant de liaison

import * as React from 'react'
import Button from '../Button/Button'
import { Link as LinkRouter } from 'react-router-dom'
import { LinkProps } from './Link.types'

function Link({ to, ...props }: LinkProps): JSX.Element {
  return <Button to={to} as={LinkRouter} {...props} />
}

export default Link

Types de liens

import { ButtonProps } from '../Button/Button.types'
import { LinkProps } from 'react-router-dom'

type RouterLinkWithButtonProps = ButtonProps & LinkProps

export interface LinkProps extends RouterLinkWithButtonProps {}

Quand je fais ce qui précède, ce problème nous vient ...

Property 'to' does not exist on type 'IntrinsicAttributes & ButtonProps'.

... ce qui est logique car le bouton n'a pas le prop to qui est requis pour le composant Link de react-router-dom.

Comment allez-vous aborder quelque chose comme ça? Où lorsque vous utilisez le Button le to prop ne doit même pas être dans le type et lorsque vous utilisez le Link le to doit être requis.

tilise

<Button>Hello</Button>
<Link to="/somewhere">Hello</Link>
11

Cela devrait fonctionner.

function Link(_props: LinkProps): JSX.Element {
  const props = { as: LinkRouter, ..._props };
  return <Button {...props} />
}

Notez que TypeScript s'applique vérifications strictes de l'affectation du littéral d'objet qui peut être assoupli en affectant un littéral d'objet à une variable au lieu de le passer directement comme, par exemple, un argument de fonction, qui est cohérent avec le React.

declare function foo(arg: { a: number }): void;

foo({ to: '', a: 1 }); // error

const arg = { to: '', a: 1 };
foo(arg); // no error
1
kimamula