Zoeken op website

reactjs - Storybook: Hoe generieke args/props types te annoteren


Context & Code

We hebben onze knop als volgt uitgebreid:

export type ButtonProps<P = Record<string, unknown>> = P & {
  children: ReactNode | string
  onClick?: () => void
  className?: string
  disabled?: boolean
  secondary?: boolean
}

const Button = <P extends Record<string, unknown>>({
  children,
  onClick,
  className,
  disabled = false,
  secondary = false,
}: ButtonProps<P>) => {
  ...
}

Deze overbelasting betekent dat we nieuwe knoppen kunnen implementeren met extra props, zonder de originele knop te verpesten, zoals:

const FooterTwoButtons = ({
  secondaryOnClick,
  secondaryIconType,
  icon,
  className,
  ...props
}: ButtonProps<TwoButtonsProps>) => {
  return (
    <div className={clsx('grid grid-cols-5', className)}>
      <Button onClick={secondaryOnClick} secondary>
        {(secondaryIconType !== undefined && (
          <Icon type={secondaryIconType} />
        )) ||
          (icon !== undefined && icon)}
      </Button>
      <FooterButton {...props}>{props.children}</FooterButton>
    </div>
  )
}

Het is super handig omdat het toestaat dat meer tijdelijke knopcomponenten worden uitgebreid vanuit ons basistype. Alles compileert en werkt zoals verwacht, behalve voor Storybook...

Probleem

Het lijkt erop dat ik geen vragen/problemen kan vinden over een modern storybook-component dat generieke props toestaat.

Verhaal van ExtendedButtonProps:

export const ButtonExtendedProps: ComponentStory<typeof Button> = ({
  secondaryIconType,
  children,
  ...props
}: ButtonProps<ExtendedProps>) => {
  return (
    <div>
      <Button secondaryIconType={secondaryIconType} {...props}>
        {children}
      </Button>
    </div>
  )
}
ButtonExtendedProps.args = {
  ...Default.args,
  secondaryIconType: 'CircledX',
}

Hier is de tsc-compilerfout, die verschijnt op ButtonExtendedProps in de bovenstaande code:

module ButtonExtendedProps
const ButtonExtendedProps: ComponentStory<(<P extends Record<string, unknown>>({ children, onClick, className, disabled, secondary, }: ButtonProps<P>) => JSX.Element)>
Type '{ ({ secondaryIconType, children, ...props }: ButtonProps<ExtendedProps>): JSX.Element; args: Partial<Record<string, unknown> & { children: ReactNode; onClick?: (() => void) | undefined; className?: string | undefined; disabled?: boolean | undefined; secondary?: boolean | undefined; }> | undefined; }' is not assignable to type 'ComponentStory<(<P extends Record<string, unknown>>({ children, onClick, className, disabled, secondary, }: ButtonProps<P>) => Element)>'.
  Type '{ ({ secondaryIconType, children, ...props }: ButtonProps<ExtendedProps>): JSX.Element; args: Partial<Record<string, unknown> & { children: ReactNode; onClick?: (() => void) | undefined; className?: string | undefined; disabled?: boolean | undefined; secondary?: boolean | undefined; }> | undefined; }' is not assignable to type 'ArgsStoryFn<ReactFramework, Record<string, unknown> & { children: ReactNode; onClick?: (() => void) | undefined; className?: string | undefined; disabled?: boolean | undefined; secondary?: boolean | undefined; }>'.
    Types of parameters '__0' and 'args' are incompatible.
      Type 'Record<string, unknown> & { children: ReactNode; onClick?: (() => void) | undefined; className?: string | undefined; disabled?: boolean | undefined; secondary?: boolean | undefined; }' is not assignable to type 'ButtonProps<ExtendedProps>'.
        Property 'secondaryIconType' is missing in type 'Record<string, unknown> & { children: ReactNode; onClick?: (() => void) | undefined; className?: string | undefined; disabled?: boolean | undefined; secondary?: boolean | undefined; }' but required in type 'ExtendedProps'.ts(2322)

Kan iemand zien wat ik hier gemist heb? Is er een pagina in de Storybook-documentatie die voorbeelden hiervan geeft? Ik heb vandaag nogal wat rondgekeken, maar ik weet niet welke zoekwoorden ik moet gebruiken. Alle tips worden zeer gewaardeerd. Bedankt.

Antwoord #1

Zoals het zou gebeuren, ComponentStory<typeof Button> === Story<ButtonProps>

Dus het resulterende verhaalhandtekening zag eruit als:

export const ButtonExtendedProps: Story<ButtonProps<ExtendedProps>> = ({
  altIconType,
  altClassName,
  altAriaLabel,
  children,
  clean,
  ...props
}: ButtonProps<ExtendedProps>) => {