【问题标题】:Is it possible to dynamically render elements with props using TypeScript?是否可以使用 TypeScript 动态渲染带有道具的元素?
【发布时间】:2026-01-03 17:05:02
【问题描述】:

我一直在 SO 和整个网络上寻找解决方案,但我似乎无法确定。

我有两个组件,LinkButton。长话短说:它们是 <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>
  );
};

我尝试将 LinkButton 组件的通用逻辑提取到单个 Component 中,但是当我传播 ...rest 道具时,我得到 TypeScript 对我大喊大叫。从错误来看,似乎是因为我无法解释 &lt;a&gt; 道具被传播到 &lt;button&gt; 元素的可能性,反之亦然。

我想将LinkButton 保留为单独的组件,而不是将类型指定为prop,以便在实现组件时明确开发人员的意图。

有没有可能将通用逻辑提取到一个中心组件中,LinkButton 都可以简单地充当包装器?例如:

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
  • 我认为你为这个问题简化了你的代码,但这让我感到困惑,因为你渲染了两次 &lt;a&gt;&lt;button&gt; 并且你将像 showChevron 这样的道具一直传递到DOM。

标签: javascript reactjs typescript


【解决方案1】:

在传播我的道具的rest 时,能够使用as any 解决类型断言:

return (
  <Element className={classes} {...(rest as any)}>
    <Content {...props} />
  </Element>
);

【讨论】:

    最近更新 更多