'React component type in TypeScript

What is the correct way to describe the type of a react component in TypeScript? Say we have a function which returns a react component. The function:

const getTabContent: () => ReactElement = () => {
  switch (tab) {
    case 1:
      return <Images images={images} onSelect={onSelect}/>;
    default:
      return <Search onSelect={onSelect}/>;
  }
};

Here I describe the returning type as ReactElement, but I'm wondering whether it's correct or I should describe it as ReactComponentElement or even somehow completely differently? Also those both types are generics and how to fully describe them if one of them is correct?

UPD ReactElement seems to fit here, because, for example, FC (FunctionComponent) returns it



Solution 1:[1]

The correct type for a functional component is React.FunctionComponent or React.FC which is a shortcut alias for it

import React, { FC } from 'react';

const getTabContent: FC = () => {
  switch (tab) {
    case 1:
      return <Images images={images} onSelect={onSelect}/>;
    default:
      return <Search onSelect={onSelect}/>;
  }
};

The FC type simply add the children property to the props argument of the functional component so you can access it:

const SomeComponent: FC = ({ children }) => (
  <div className="hello">{children}</div>
);

FC is a generic type so you can "add" props to your component:

interface SomeComponentProps {
  foo: string;
}

const SomeComponent: FC<SomeComponentProps> = ({ children, foo }) => (
  <div className={`Hello ${foo}`}>{children}</div>
);

Solution 2:[2]

If you want to use FunctionComponent with class Component, Then use React.ComponentType

Solution 3:[3]

TypeScript comes with powerful type inference. Just use it in most places. Only top-level components required fine-grained interfaces.

For example, here resulting type will be computed as JSX.Element

const getTabContent = ({ tab, onSelect }: { tab: number, onSelect: (ev: React.SyntheticEvent) => void }) => {
  switch (tab) {
    case 1:
      return <Image src="123"/>;
    default:
      return <Search onSelect={onSelect}/>;
  }
};

Solution 4:[4]

Considering this built-in definition in React:

type PropsWithChildren<P> = P & {
    children?: React.ReactNode;
}

I am using React.ReactNode. It is defined as

type ReactNode = ReactChild | ReactFragment | ReactPortal | boolean | null | undefined;

Solution 5:[5]

The best option would be ComponentType. If you are strict about the functional component, You can make use of FC. In some cases, You might want both class component type and functional component type support. (i.e. Defining a prop type where the prop is expecting a component, either functional or class).

The recommended way is to use ComponentType in the type definition (i.e. ProopTypes) and FC when you want to define return type etc.

FYI, Here is the definition of ComponentType, FC in typescript

type ComponentType<P = {}> = ComponentClass<P> | FunctionComponent<P>;
type FC<P = {}> = FunctionComponent<P>;

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 MJ Studio
Solution 3 Alexander Alexandrov
Solution 4 igo
Solution 5 Kiran Maniya