【发布时间】:2026-01-03 17:05:02
【问题描述】:
我一直在 SO 和整个网络上寻找解决方案,但我似乎无法确定。
我有两个组件,Link 和 Button。长话短说:它们是 <a> 和 <button> 元素的包装器,但增加了选项,例如右侧的 V 形、左侧的图标、全角模式等。
这是我目前所拥有的(和here's the code running on typescriptlang.org/play):
type Variant = "primary" | "secondary" | "tertiary";
interface CommonProps {
variant?: Variant;
showChevron?: boolean;
icon?: IconDefinition;
fullWidth?: boolean;
small?: boolean;
}
interface LinkOnlyProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
href: string;
}
interface ButtonOnlyProps
extends React.ButtonHTMLAttributes<HTMLButtonElement> {
onClick: React.MouseEventHandler<HTMLButtonElement>;
}
export type LinkProps = CommonProps & LinkOnlyProps;
export type ButtonProps = CommonProps & ButtonOnlyProps;
export const Link = (props: LinkProps) => {
const {
children,
showChevron,
icon,
fullWidth,
variant,
small,
className,
...rest
} = props;
const { classes } = initButton(props);
return (
<a className={classes} {...rest}>
<Content {...props} />
</a>
);
};
export const Button = (props: ButtonProps) => {
const {
children,
showChevron,
icon,
fullWidth,
variant,
small,
className,
...rest
} = props;
const { classes } = initButton(props);
return (
<button className={classes} {...rest}>
<Content {...props} />
</button>
);
};
我尝试将 Link 和 Button 组件的通用逻辑提取到单个 Component 中,但是当我传播 ...rest 道具时,我得到 TypeScript 对我大喊大叫。从错误来看,似乎是因为我无法解释 <a> 道具被传播到 <button> 元素的可能性,反之亦然。
我想将Link 和Button 保留为单独的组件,而不是将类型指定为prop,以便在实现组件时明确开发人员的意图。
有没有可能将通用逻辑提取到一个中心组件中,Link 和 Button 都可以简单地充当包装器?例如:
export const Link = (props: LinkProps) => {
return <Component element="a" {...props} />;
}
export const Button = (props: ButtonProps) => {
return <Component element="button" {...props} />;
}
【问题讨论】:
-
typescriptlang.org/play 上的可重现示例将帮助其他人帮助您????
-
很棒的提示,@AlekseyL。-谢谢!我按照建议创建了一个可重现的示例并将其添加到问题内容中。 ????♂️
-
看起来你无法绕过类型断言 (
as any).. tsplay.dev/NnX6eW -
我认为你为这个问题简化了你的代码,但这让我感到困惑,因为你渲染了两次
<a>或<button>并且你将像showChevron这样的道具一直传递到DOM。
标签: javascript reactjs typescript