首页 > 解决方案 > 是否可以使用 TypeScript 动态渲染带有道具的元素?

问题描述

我一直在挖掘 SO 和整个网络以寻求解决方案,但我似乎无法确定它。

我有两个组件,LinkButton. 长话短说:它们是<a><button>元素的包装器,但增加了选项,例如右侧的 V 形、左侧的图标、全角模式等。

这是我到目前为止所拥有的(这是在 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>
  );
};

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

我想保留LinkButton作为单独的组件,而不是将类型指定为道具,以便在实现组件时开发人员的意图很清楚。

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

export const Link = (props: LinkProps) => {
  return <Component element="a" {...props} />;
}
export const Button = (props: ButtonProps) => {
  return <Component element="button" {...props} />;
}

标签: javascriptreactjstypescript

解决方案


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

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

推荐阅读