React component type in TypeScript

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>
);

Edit: React 18 update

Since React 18, FC doesn't add the children prop implicitly and offers an explicit way to do so with the PropsWithChildren generix type

Example:

type SomeComponentProps = { a: string };

const SomeComponent: FC<SomeComponentProps> = ({ a }) => <div>{a}</div>;

// This will fail when using the following expression
<SomeComponent>Hey I'm a child</SomeComponent>

Usage with children:

type ComponentWithChildrenProps = PropsWithChildren<{ a: string }>;

const ComponentWithChildrenProps: FC<ComponentWithChildrenProps> = ({
  a,
  children
}) => <div>{a} and {children}</div>

This allows to have a children prop a bit stricter. e.g.

type StrictCompProps = { children: string };

const StrictComp: FC<StrictCompProps> = ({ children }) => <div>{children}</div>;

// This will fail
<StrictComp><span>hey</span></StrictComp>

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;

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


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}/>;
  }
};