打字稿:带有来自@ material-ui

时间:2020-06-29 16:42:31

标签: reactjs typescript material-ui

我正在尝试在@ material-ui Button组件之上添加自定义逻辑。为此,我正在创建一个包装原始Button并可以正常运行的组件。

我的问题是要正确键入它,尤其是要从原始组件中获取道具。我遵循https://material-ui.com/guides/typescript/#usage-of-component-prop直到添加React.forwardRef()为止。

没有forwardRef的工作版本:

import { Button, ButtonProps } from '@material-ui/core'
import React from 'react'

type ExtraProps = {
  target?: string
  rel?: string
  href?: string
  color?: 'default' | 'primary' | 'secondary'
}

// see https://material-ui.com/guides/typescript/#usage-of-component-prop
type Props<C extends React.ElementType> = ButtonProps<C, { component?: C }> & ExtraProps

const CustomButton = <C extends React.ElementType>({
  children,
  target,
  rel,
  href,
  ...rest
}: Props<C>) => {
  const relValue = target === '_blank' ? 'noopener noreferrer' : rel

  const linkValues = href ? { href, target, rel: relValue } : undefined

  return (
    <Button {...linkValues} {...rest}>
      {children}
    </Button>
  )
}

具有React.forwardRef的非工作版本:

import { Button, ButtonProps } from '@material-ui/core'
import React from 'react'

type ExtraProps = {
  target?: string
  rel?: string
  href?: string
  color?: 'default' | 'primary' | 'secondary'
}

// see https://material-ui.com/guides/typescript/#usage-of-component-prop
export type Props<C extends React.ElementType> = ButtonProps<C, { component?: C }> & ExtraProps

const CustomButton = React.forwardRef<HTMLButtonElement, Props<React.ElementType>>(
  ({ children, target, rel, href, ...rest }, ref) => {
    const relValue = target === '_blank' ? 'noopener noreferrer' : rel

    const linkValues = href ? { href, target, rel: relValue } : undefined

    return (
      <Button {...linkValues} {...rest} ref={ref}>
        {children}
      </Button>
    )
  }
)

当我说“无效”时,是因为CustomButton的类型是:

React.ForwardRefExoticComponent<Pick<Props<React.ElementType<any>>, string | number | symbol> & React.RefAttributes<HTMLButtonElement>>

代替

<C extends React.ElementType<any>>({ children, target, rel, href, ...rest }: Props<C>) => JSX.Element

这意味着我可以将任何道具传递给CustomButton,TS完全不执行合同。

我应该如何用React.forwardRef()修复版本,以便正确键入?

Codesandbox演示:https://codesandbox.io/s/boring-hertz-0hutt?file=/src/App.tsx

1 个答案:

答案 0 :(得分:0)

forwardRef不是通用的。这是万恶之源。我也在努力实现类型安全。现在,我有此解决方案:

$P

(注:我正在使用样式组件)

相关问题