Official ReactJs documentation recommends to create components following the dot notation like the React-bootstrap library:
<Card>
<Card.Body>
<Card.Title>Card Title</Card.Title>
<Card.Text>
Some quick example text to build on the card title and make up the bulk of
the card's content.
</Card.Text>
</Card.Body>
</Card>
Thanks to this question, I know that I can create this structure using functional components just like that in javascript:
const Card = ({ children }) => <>{children}</>
const Body = () => <>Body</>
Card.Body = Body
export default Card
Using TypeScript I decided to add the corresponding types to it:
const Card: React.FunctionComponent = ({ children }): JSX.Element => <>{children}</>
const Body: React.FunctionComponent = (): JSX.Element => <>Body</>
Card.Body = Body // <- Error: Property 'Body' does not exist on type 'FunctionComponent<{}>'
export default Card
Problem is now that TypeScript don't allow the assignment Card.Body = Body
and give me the error:
Property 'Body' does not exist on type 'FunctionComponent<{}>'
So how can I type this correctly in order to use this code structure?
There are many we can create Functional Components in typescript. In Typescript React Component, Function takes props object and returns JSX data. Declare Normal Function with props parameters of the type above MessageProps (use type or interface).
The question mark dot (?.) syntax is called optional chaining in TypeScript and is like using dot notation to access a nested property of an object, but instead of causing an error if the reference is nullish, it short-circuits returning undefined .
Of course, you can still pass props from parent to child with functional components but the big difference is that you'll need to declare them in your functional component callback just as you would with any other type of function. Now you can access those props.
const Card: React.FunctionComponent & { Body: React.FunctionComponent } = ({ children }): JSX.Element => <>{children}</>
const Body: React.FunctionComponent = (): JSX.Element => <>Body</>
Card.Body = Body;
Or more readable:
type BodyComponent = React.FunctionComponent;
type CardComponent = React.FunctionComponent & { Body: BodyComponent };
const Card: CardComponent = ({ children }): JSX.Element => <>{children}</>;
const Body: BodyComponent = (): JSX.Element => <>Body</>;
Card.Body = Body;
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