React with TypeScript: Components as Function Declarations vs. Function Expressions

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. ), we have to ask ourselves, “what are we annotating and what type of value does this variable 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. ), 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 . If you haven’t seen before, you’ll notice from the 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 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 which will automatically include the prop for us:

Typing Props with a Function Declaration

We can do the same thing with a function declaration:

And the same for using :

Pretty neat, huh?

Credit to Chau Tran for teaching me about this on Twitter!

LAST UPDATED: December 17, 2019

More about:

Joe Previte