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