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 Link
s 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>
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