When I first started learning TypeScript and using it with React, I followed patterns. A friend showed me how to type a component. I used that as an example whenever I created a new component. This example looked something like this:
Experimenting with this pattern, I thought to myself, “If I want to declare a component using the function keyword, then I bet I can do the same thing.”
function MyComponent(): React.FC {
return <h1>Hello, world!</h1>
}
Sadly, this is not valid. Instead of investigating deeper, I decided to stick with what worked (using function expressions like the first example). Eight months later, after diving deeper into TypeScript, I’ve finally learned the difference and understand why my first attempt didn’t work.
Typing a React Component as a Function Expression
When we type a React component as a function expression (i.e. const MyComponent: React.FC), we have to ask ourselves, “what are we annotating and what type of value does this variable MyComponent hold?”
We’re annotating the function type because this variable holds a function.React.FC indicates a “React Function Component”. So that’s why we type it this way.
Typing a React Component as a Function Declaration
In the other instance, when we type a React component as a function declaration (i.e. function MyComponent), we ask the same thing.
This time, we’re annotating the function return type. This explains why we can’t use the same type! We instead need to tell TypeScript, “Hey! This function here is going to return a React component.” So what does that look like? Like this:
function MyComponent(): React.ReactNode {
return <h1>Hello, world!</h1>
}
Now, TypeScript knows that this function will return some type of ReactNode. If you haven’t seen ReactNode before, you’ll notice from the @types/react declaration file that it is a union type that looks like this:
These are all the valid things that can be returned by a component. Feel free to take a look at the source code here.
And now you know how to properly type a React component as both function expressions and function declarations! Check out the [react-typescript-cheatsheet](https://github.com/typescript-cheatsheets/react-typescript-cheatsheet) to learn more.
Typing Props with a Function Expression
When your components accept props, it’s important to know where those get added in as well. Here’s an example:
When I first started learning TypeScript and using it with React, I followed patterns. A friend showed me how to type a component. I used that as an example whenever I created a new component. This example looked something like this:
Experimenting with this pattern, I thought to myself, “If I want to declare a component using the
function
keyword, then I bet I can do the same thing.”Sadly, this is not valid. Instead of investigating deeper, I decided to stick with what worked (using function expressions like the first example). Eight months later, after diving deeper into TypeScript, I’ve finally learned the difference and understand why my first attempt didn’t work.
Typing a React Component as a Function Expression
When we type a React component as a function expression (i.e.
const MyComponent: React.FC
), we have to ask ourselves, “what are we annotating and what type of value does this variableMyComponent
hold?”We’re annotating the function type because this variable holds a function.
React.FC
indicates a “React Function Component”. So that’s why we type it this way.Typing a React Component as a Function Declaration
In the other instance, when we type a React component as a function declaration (i.e.
function MyComponent
), we ask the same thing.This time, we’re annotating the function return type. This explains why we can’t use the same type! We instead need to tell TypeScript, “Hey! This function here is going to return a React component.” So what does that look like? Like this:
Now, TypeScript knows that this function will return some type of
ReactNode
. If you haven’t seenReactNode
before, you’ll notice from the@types/react
declaration file that it is a union type that looks like this:These are all the valid things that can be returned by a component. Feel free to take a look at the source code here.
And now you know how to properly type a React component as both function expressions and function declarations! Check out the
[react-typescript-cheatsheet](https://github.com/typescript-cheatsheets/react-typescript-cheatsheet)
to learn more.Typing Props with a Function Expression
When your components accept props, it’s important to know where those get added in as well. Here’s an example:
In addition, we can use a handy type called
PropsWithChildren
which will automatically include thechildren
prop for us:Typing Props with a Function Declaration
We can do the same thing with a function declaration:
And the same for using
PropsWithChildren
:Pretty neat, huh?
Credit to Chau Tran for teaching me about this on Twitter!
Contributor’s Bio
Joe lives in sunny Scottsdale, Arizona. He is a Software Engineer at Echobind and has been building software for the last 3 years.
LAST UPDATED: December 17, 2019