網站搜尋

reactjs - Storybook:如何標註通用參數/屬性類型


上下文與程式碼

我們這樣擴展了按鈕:

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>) => {
  ...
}

這種重載意味著我們可以使用額外的屬性實現新的按鈕,而不會弄亂原本的按鈕,例如:

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

這非常好,因為它允許更多短暫的按鈕組件從我們的基礎類型擴展。一切都能編譯並按預期運作,除了 storybook...

問題

我似乎找不到任何關於現代故事書組件允許通用屬性的問題/疑問。

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',
}

這裡是 tsc 編譯器錯誤,出現在上述代碼中的 ButtonExtendedProps:

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)

有人能看出我在這裡漏了什麼嗎?故事書文件中有提供這個的範例頁面嗎?我今天四處翻找過,但不確定該搜尋哪些關鍵字。任何建議都非常感謝。謝謝。

答案#1

碰巧的是,ComponentStory<typeof Button> === Story<ButtonProps>

所以最終的故事簽名看起來像這樣:

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