I have a component that can accept another component as a prop.
Very simplified example:
interface Props {
Comp: React.ComponentClass<unknown> | React.SFC<unknown>
}
const MyComp: React.FC<props> = ({ Comp }) => {
return React.createElement(Comp)
}
What would be the most simple type for Comp that accepts functional components, class based components, etc?
The type definition of createElement makes it look rather complicated https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/react/v16/index.d.ts#L286
React has its own, built-in way of type checking called “prop types”. Together with TypeScript this provides a full, end-to-end type-checking experience: Compiler and run-time.
Within TypeScript, React.Component is a generic type (aka React.Component<PropType, StateType> ), so you want to provide it with (optional) prop and state type parameters: type MyProps = { // using `interface` is also ok message: string; }; type MyState = { count: number; // like this }; class App extends React.
By invoking them between the opening and closing tags of a JSX element, you can use React children for entering data into a component. The React children prop is an important concept for creating reusable components because it allows components to be constructed together.
Want to pass React components down as a prop in TypeScript? Use React.ReactNode type definition. There's other ways, but this is a better solution. pic.twitter.com/6jjADp1Fnr First, if you’re looking to become an expert React developer for 2021, you might want to look into Wes Bos, Advanced React course for just $97.00 (30% off).
React.ComponentType? React.ReactNode? React.ComponentType<P> is the type for either a class component ( React.ComponentClass<P>) or function component ( React.FunctionComponent<P> aka React.FC<P>) which takes props P. (FYI, React.ReactNode and React.ReactElement are the types for the JSX returned by the component - not for a callable component)
PropTypes provide built-in typechecking capabilities when writing a React app. Checking the type of prop in a React component in a large application helps catch bugs at run-time. Typically in a React app, you will need to install the package yarn add prop-types.
If you go and explore the type definition files for the most popular React re-usable component libraries you will notice that most of them use interfaces for props instead, so you could conclude that this is the globally accepted community approach for some reason.
React.ComponentType<P>
is the type for either a class component (React.ComponentClass<P>
) or function component (React.FunctionComponent<P>
aka React.FC<P>
) which takes props P
.
(FYI, React.ReactNode
and React.ReactElement
are the types for the JSX returned by the component - not for a callable component)
You do not want to use <unknown>
in your Props
type. You want to declare that the component requires only the props which you are providing when you call React.createElement(Comp)
(you call also use JSX and return <Comp/>
). In this case you are providing no props, so it would be React.ComponentType<{}>
or just React.ComponentType
since {}
is the default for P
.
interface Props {
Comp: React.ComponentType;
}
const MyComp: React.FC<Props> = ({ Comp }) => {
return <Comp />
}
with some props:
interface Props {
Comp: React.ComponentType<{someKey: string}>;
}
const MyComp: React.FC<Props> = ({ Comp }) => {
return <Comp someKey="someValue" />
}
You will get an error if you call Comp
without providing someKey
, which is good! You don't get that error when calling React.createElement(Comp)
because for some reason the props
argument is optional. So in my opinion the JSX approach is better.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With