如何处理一个重载中存在而另一个重载中不存在的属性?

时间:2019-01-23 00:20:49

标签: reactjs typescript overloading

我使用React 16和Typescript3。我创建一个组件,该组件根据是否设置了 to 属性返回按钮或链接。该组件可能具有 to onClick 属性,但不能两者兼有。

我发现issue on TypeScript repository准确地描述了我的问题,并且在2.2版本中似乎已解决,但是以某种奇怪的方式,它不起作用。

为此,我创建了接口并按如下方式使用它们:

interface GeneralProps {/* whatever here, it works */}
interface LinkProps extends GeneralProps { to: string }
interface ButtonProps extends GeneralProps { 
  onClick?: (e: React.MouseEvent<HTMLButtonElement>) => void 
  // onClick might be as well undefined
}

function Button (props: LinkProps | ButtonProps): JSX.Element {
  const Component: AnyStyledComponent = props.to ? Link : Button
  return (
    <Component to={props.to} onClick={props.onClick}>
      {props.children}
    </Component>
  )
}

或者,我也尝试这样编写此函数:

function Button (props: LinkProps): JSX.Element
function Button (props: ButtonProps): JSX.Element {
  const Component: AnyStyledComponent = props.to ? Link : Button
  return (
    <Component to={props.to} onClick={props.onClick}>
      {props.children}
    </Component>
  )
}

上面的Button函数的第一个实现抛出两个错误,第二个仅抛出第一个错误:

  

“链接属性|类型”上不存在属性“至” ButtonProps”。类型“ ButtonProps”上不存在属性“ to”。

     

“ LinkProps |类型”上不存在属性“ onClick” ButtonProps”。类型“ LinkProps”不存在属性“ onClick”。

为避免错误,我提出了愚蠢的解决方法:

function Button (props: LinkProps | ButtonProps): JSX.Element {
  const properties = Object.keys(props)
  const to = properties.find((el) => el === 'to')
  const Component: AnyStyledComponent = to ? Link : Button
  return (
    <Component {...props}>
      {props.children}
    </Component>
  )
}

但是,这不能解决我的问题,因为我仍然可以将 to onClick 属性都传递给Button组件。

我的代码中是否存在某种错误导致我无法实现自己的目标?我应该从另一个角度来解决这个问题吗?或者这显然是不可能的?

1 个答案:

答案 0 :(得分:1)

由于发布了jcalz线程,我想出了一个实际上可以按预期工作的解决方案。我的解决方案有所不同(我使用接口,而不是类型),但是该线程让我想到了使用Never类型。我以前也使用过它,但是它是必需的属性,然后打字稿要求传递一个值,当您传递它时,打字稿要求将其删除。从不输入属性必须是可选的。

interface GeneralProps {/* whatever here, it works */}
interface LinkProps extends GeneralProps { 
  to: string
  onClick?: never
}
interface ButtonProps extends GeneralProps { 
  onClick?: (e: React.MouseEvent<HTMLButtonElement>) => void 
  to?: never
}
function Button (props: LinkProps | ButtonProps): JSX.Element { ... }

在当前解决方案中,打字稿始终会识别类型上同时存在 to onClick 这两个属性,当我输入这两个属性时都不会引发错误属性,但是当我同时传递这两个属性时抛出。