[英]Union types with TypeScript and React
我想要一个组件根据给定的特定属性的值接受不同的 props。 类似于以下内容。
const Button: React.FC<TButton> = ({ href, children, ...rest }) => {
if (href) {
return <a href={href} {...rest}>{children}</a>
}
return <button {...rest}>{children}</button>
}
type TButton = { href: string & IAnchor } | { href: undefined & IButton }
interface IAnchor extends React.AnchorHTMLAttributes<HTMLAnchorElement> {}
interface IButton extends React.ButtonHTMLAttributes<HTMLButtonElement> {}
问题是,无法弄清楚如何正确地经历这个。 我的意思是,似乎条件没有被正确解析或解释。
如果您想仔细查看该问题,请参阅此 StackBlitz 。
似乎您基本上尝试使用歧视 union 。 但似乎它不适用于...rest
。 所以为了让它工作
为两个接口添加额外的属性,比如将用作判别type
interface IAnchor extends React.DetailedHTMLProps<React.AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement> { type: 'anchor' href: string } interface IButton extends React.ButtonHTMLAttributes<HTMLButtonElement> { type: 'button' }
接受porps
,然后在条件分支中销毁它们
const Button: React.FC<TButton> = (props): JSX.Element => { if (props.type === 'anchor') { const { type, href, children, ...rest } = props; return ( <a href={href} {...rest}> {children} </a> ) } const { type, children, ...rest } = props; return <button {...rest}>{children}</button> }
查看 工作示例
我查看了您的 StackBlitz,并能够使用ts-toolbelt库来解决这个问题:
首先,让我们定义两个不同的可能的 prop 类型(所有锚 props 和所有按钮 props),将它们组合为一个严格的联合并使用类型保护让我们的 React 组件知道我们何时使用哪组 props:
import { Union } from 'ts-toolbelt'
type TButton = Union.Strict<IAnchor | IButton>
interface IAnchor extends React.AnchorHTMLAttributes<HTMLAnchorElement> {}
interface IButton extends React.ButtonHTMLAttributes<HTMLButtonElement> {}
const isAnchor = (props: TButton): props is IAnchor => {
return props.href !== undefined;
}
const isButton = (props: TButton): props is IButton => {
return props.type !== undefined
}
现在,让我们编写可以是按钮或锚点的自定义组件:
const Button: React.FC<TButton> = ({ children, ...props }): JSX.Element => {
if (isAnchor(props)) {
return (
<a href={props.href} {...props}>
{children}
</a>
)
} else if (isButton(props)) {
return <button {...props}>{children}</button>
}
}
您可以在此 StackBlitz 中查看它的工作情况。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.