Home > Software design >  React Typescript - Types problem | One component that renders sub component
React Typescript - Types problem | One component that renders sub component

Time:02-12

Parent Component: Font
Sub Component: FontHeading, FontText, FontSubTitle.

  return (
    <>
      {type === "title" && <FontTitle as={as} variant={variant as HeadingVariants}>{children}</FontTitle>}
      {type === "subtitle" && <FontSubtitle>{children}</FontSubtitle>}
      {type === "iperlink" && <FontIperLink>{children}</FontIperLink>}
    </>
  );

export type IFont = {
  type: 'title' | 'subtitle' | 'link',
  children: React.ReactNode,
  variant: HeadingVariants | TextVariants | LinkVariants;
  setRef?: React.Ref<HTMLDivElement>;
}

export type IFontTitle = {
  as?: "h1" | "h2" | "h3" | "h4" | "h5";
  variant: HeadingVariants
}

export type IFontSubTitle = {
  variant: TextVariants
}

export type IFontLink = {
  href: string;
  variant: LinkVariants;
}

How can I tell that if <Field type="title" .... /> then it needs to accept props that are of IFontTitle ? Viceversa with type="variant" or type="link". Also would be great if it's auto select the correct variant, any help is appreciated..

Thanks

CodePudding user response:

I suppose, generic will be more suitable in your case (read from bottom to top).

interface Link extends BaseFont<'link', LinkVariants, HTMLLinkElement> {
  href: string;
}

interface Subtitle extends BaseFont<'subtitle', TextVariants, HTMLDivElement> {}

type TitleTag = "h1" | "h2" | "h3" | "h4" | "h5";

interface Title extends BaseFont<'title', HeadingVariants, HTMLHeadingElement> {
  tag?: TitleTag;
}

interface BaseFont<T, V, R> {
  type: T;
  variant: V;
  children: ReactNode;
  ref?: Ref<R>;
}

And don't use verb, if you name an instance but not some function.

CodePudding user response:

You can use union types for that:

type SharedProps = {
  children: React.ReactNode,
  setRef?: React.Ref<HTMLDivElement>;
}
type TFontTitle = {
    type: 'title'
    as?: "h1" | "h2" | "h3" | "h4" | "h5";
    variant: HeadingVariants
}
type TFontSubTitle = {
    type: 'subtitle'
    variant: TextVariants
}
type TFontLink = {
    type: 'link'
    href: string;
    variant: LinkVariants;
}
type UnionProps = TFontTitle | TFontSubTitle | TFontLink
type Props = UnionProps & SharedProps
  • Related