Home > Software design >  how could I specify a type for a react component in typescript?
how could I specify a type for a react component in typescript?

Time:11-10

I'd like to send a react custom component to another component as a property

event-logistics.tsx // component name
    
    import { DateIcon } from "../../ui/icons/DateIcon";
    import LogisticsItem from "./logistics-item";

            <LogisticsItem icon={DateIcon}>
              <time>{humanReadableDate}</time>
            </LogisticsItem>

it gives me this error on icon property :

JSX element type 'Icon' does not have any construct or call signatures.ts(2604)
const Icon: (({ height, width, color, ...props }: SVGProps<SVGSVGElement>) => Element) | undefined

as you see I'd like to send the 'DateIcon' which is a react SVG component to the "LogisticsItem" component as on icon property

logistics-item.tsx // component name

 import style from "./logistics-item.module.css";
 import { DetailedHTMLProps, LiHTMLAttributes, SVGProps } from "react";

export const LogisticsItem: React.FunctionComponent<
  DetailedHTMLProps<LiHTMLAttributes<HTMLLIElement>, HTMLLIElement> & {
    icon?: ({
      height,
      width,
      color,
      ...props
    }: SVGProps<SVGSVGElement>) => Element;
  }
 > = ({ title, children, icon, ...rest }) => {
  const Icon = icon;
  return (
    <li className={style.item}>
      <span className={style.icon}>
        <Icon />
      </span>
      <span className={style.content}>{children}</span>
    </li>
  );
};

export default LogisticsItem;

CodePudding user response:

Just use FC<SVGProps<SVGSVGElement>> instead of

{
    icon?: ({
      height,
      width,
      color,
      ...props
    }: SVGProps<SVGSVGElement>) => Element

Consider this example:

import React, { FC, createElement } from 'react';
import { DetailedHTMLProps, LiHTMLAttributes, SVGProps } from "react";


export const LogisticsItem: React.FunctionComponent<
  DetailedHTMLProps<LiHTMLAttributes<HTMLLIElement>, HTMLLIElement> & {
    icon: FC<SVGProps<SVGSVGElement>>;
  }
> = ({ title, children, icon, ...rest }) => {
  const Icon = icon;

  return (
    <li>
      <span>
        <Icon />
      </span>
      <span >{children}</span>
    </li>
  );
};

const DateIcon = ({ height = "24px", width = "24px", color = "black", ...props }: React.SVGProps<SVGSVGElement>) => 
  (<svg xmlns="w3.org/2000/svg" width={width} height={height} fill="none" viewBox="0 0 24 24" stroke="currentColor" {...props} > <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" /> </svg>)

const result = <LogisticsItem icon={DateIcon} />

Playground

There are no errors

  • Related