这一期CodeSandbox Example美元.

我已经定义了一个图标库,它可以导出几个图标.每个Icon将一个引用转发到其内部SVG.下面是一个例子:

type ReactIconProps = SVGProps<SVGSVGElement>;

function CheckIconInner(props: ReactIconProps, ref: Ref<SVGSVGElement>) {
  return (
    <svg
      fill="none"
      height="1em"
      ref={ref}
      stroke="currentColor"
      viewBox="0 0 24 24"
      width="1em"
      xmlns="http://www.w3.org/2000/svg"
      {...props}
    >
      <path
        d="M20 6L9 17L4 12"
        strokeLinecap="round"
        strokeLinejoin="round"
        strokeWidth={2}
      />
    </svg>
  );
}
const CheckIcon = forwardRef(CheckIconInner);

我想将这些图标用作按钮组件中的props ,以便按钮可以包含图标.请参见下面的内容:

type ReactButtonProps = ButtonHTMLAttributes<HTMLButtonElement>;

export interface ButtonProps extends ReactButtonProps {
  Icon?: ComponentType<ReactIconProps>;
}

function Button({ children, Icon, ...props }: ButtonProps) {
  return (
    <button {...props}>
      {Icon !== undefined && <Icon />}
      {children}
    </button>
  );
}

export default function App() {
  return <Button Icon={CheckIcon}>OK</Button>;
}

然而,当图标被传递给按钮(<Button Icon={CheckIcon}>OK</Button>)时,该方法抛出打字错误:

TS2322: Type 'ForwardRefExoticComponent<Omit<ReactIconProps, "ref"> & RefAttributes<SVGSVGElement>>' is not assignable to type 'ComponentType<ReactIconProps> | undefined'.
  Type 'ForwardRefExoticComponent<Omit<ReactIconProps, "ref"> & RefAttributes<SVGSVGElement>>' is not assignable to type 'FunctionComponent<ReactIconProps>'.
    Types of parameters 'props' and 'props' are incompatible.
      Type 'ReactIconProps' is not assignable to type 'Omit<ReactIconProps, "ref"> & RefAttributes<SVGSVGElement>'.
        Type 'SVGProps<SVGSVGElement>' is not assignable to type 'RefAttributes<SVGSVGElement>'.
          Types of property 'ref' are incompatible.
            Type 'LegacyRef<SVGSVGElement> | undefined' is not assignable to type 'Ref<SVGSVGElement> | undefined'.
              Type 'string' is not assignable to type 'Ref<SVGSVGElement> | undefined'.

问题是,图标需要一个裁判,但我们没有给它传一个.

两个问题:

  1. 如何指定传递给icon组件的ref是可选的?
  2. 在图标组件中使用ref是一种好做法吗?我看到了很多关于引用不应该被过度使用的建议,但也看到了组件库可能会广泛使用它.

Edit

我在an issue in the heroicons repository个用例中找到了2号的答案--大量的用例!

推荐答案

我终于找到了答案.而不是将Iconprops 键入为ComponentType<ReactIconProps>:

export interface ButtonProps extends ReactButtonProps {
  Icon?: ComponentType<ReactIconProps>;
}

我把它改成:

type ReactIconProps = SVGProps<SVGSVGElement>;
type ReactIconComponent = React.ForwardRefExoticComponent<
  Omit<ReactIconProps, "ref"> & React.RefAttributes<SVGSVGElement>
>;

export interface ButtonProps extends ReactButtonProps {
  Icon?: ReactIconComponent;
}

新的类型定义ReactIconComponent实质上用RefAttributes<SVGSVGElement>替换了ReactIconProps中的ref属性.这将为SVG元素正确地键入ref.

这是固定的CodeSandbox example英镑.

Typescript相关问答推荐

调用另一个函数的函数的Typescript类型,参数相同

创建一个通用上下文,允许正确推断其中的子项

VS代码1.88.0中未出现自动导入建议

用泛型类型覆盖父类函数导致类型y中的Property x不能赋给基类型Parent中的相同属性."'''''' "

node—redis:如何在redis timeSeries上查询argmin?

将值添加到具有不同类型的对象的元素

使用ngrok解析Angular 时出现HTTP故障

如何为父类构造函数中的修饰属性赋值?

TypeScrip原始字符串没有方法

React Typescript项目问题有Redux-Toolkit userSlice角色问题

如何避免推断空数组

try 呈现应用程序获取-错误:动作必须是普通对象.使用自定义中间件进行MySQL操作

TYPE FOR ARRAY,其中每个泛型元素是单独的键类型对,然后在该数组上循环

带投掷的收窄类型

是否可以在类型脚本中定义条件返回类型,而不在函数体中使用类型转换?

如何在具有嵌套数组的接口中允许新属性

如何在Deno中获取Base64图像的宽/高?

完全在类型系统中构建的东西意味着什么?

我是否应该在 Next.js 中的服务器组件中获取秘密数据的所有函数中使用使用服务器?

使用react+ts通过props传递数据