Getting Started with TypeScript in React

Kyle Farmer
JavaScript in Plain English
6 min readMar 25, 2021

--

As JavaScript takes over the world, TypeScript seems to be coming along for the ride. For at least half of the entry-level frontend jobs that I apply for, experience with TypeScript is listed as a requirement or “nice to have”. While no one is expecting you to be an expert in it, knowing the basics so that you can talk about it in an interview will get you ahead of most other candidates. So let’s learn some basics to get you started with a simple React app!

TypeScript is a strongly-typed static superset of JavaScript. This means the types of variables are checked at compile-time rather than run-time. A type error will also be given if the variable’s type doesn’t match up as expected. JavaScript is the opposite of this. It’s a weakly-typed dynamic language. The variables’ type is checked during run-time and variables are not bound to a specific data type. The variables still have a data type, but the type-checking constraints are lower compared to strongly-typed languages. So TypeScipt gives us type-checking abilities at compile-time in JavaScript that are not available with vanilla JavaScript. It’s a superset of JavaScript in the sense that it is built around JavaScript and can enforce certain ways of development, but you can choose to uses as much or as little TypeScript as you want. Everything that you code in vanilla JavaScript will still work just like always but is also subjected to whatever development constraints you add in with TypeScript. The end result allows for errors to be caught earlier, easier navigation by other developers, and quicker execution of our code.

Let’s dive right in. To get started, make sure you have at least version 2.1 of create-react-app installed. The next step is just a slight amendment to the way you are used to creating a new project in React:

npx create-react-app name-of-your-app --template typescript

or

yarn create react-app name-of-your-app --template typescript

This should mostly look familiar, with the addition of tsconfig.json, react-app-env.d.ts files and the new .ts and .tsx file types where .js was before:

create-react-app ts-example-app — template typescript
create-react-app no-ts-example

The tsconfig.json file indicates that the directory it is stored in is the root directory of the project. It specifies the root files and compiler options for our project:

tsconfig.json

In “compilerOptions”, “target” is the version of JavaScript we are compiling to. HOWEVER, see that “noEmit” is set to true by default. This means that our code will not be compiled and emitted from this file, it will only type-checked. The array within “include” tells us that everything in the “src” directory will be included in the type-checking. The option “jsx”: “react-jsx” tells us that JSX is supported in the .tsx files. Read more about Compiler Options here.

react-app-env.d.ts

The react.app.env.d.ts file contains a reference to another d.ts file inside of “react-scripts” module. A d.ts file contains TypeScript type definitions. This react-app.d.ts file defines the types for various modules. For example, if you import a .jpeg, it will tell React the type of the return value (.jpeg returns type string). See below:

react-app.d.ts

Now that we’ve had a look under the hood, let’s get started by creating a new functional component for a button. We will use React.FC, which is actually provided to us by React, to declare the component type as a functional component. There are mixed opinions about whether or not to use React.FC (read about them here), but since we are just beginning we aren’t going to concern ourselves with that right now. Next, we can declare the types of props (see a full list here) being passed down to the component via type aliases or interfaces. Interfaces are more associated with object-oriented programming, so we are going to use type aliases, due to the functional programming nature of React. As TypeScript has evolved, the differences between type aliases and interfaces have become smaller. Read more about them here. Let’s have the Button component accept the prop named buttonText with a type of string. Our new Button component should look like this:

Button.tsx

Now let’s convert our App component to a functional component and pass down the buttonText. When we add our Button component to App, we notice that React now fails to compile because we haven't defined the buttonText property in Button. If we press control + spacebar while inside of Button, we can see what is available to be passed down to the component, thanks TypeScript!

App.tsx

Let’s set up our Button component to accept a count and a function that will increment the count by 1 each time the button is clicked. In the type alias Props, We add count with the type number, and onClick with an arrow function that doesn't return anything or take an argument:

Button.tsx

Now, in the App component, let’s pass the string “click me” as the buttonText prop. Let’s also create a count for the number of times the button is clicked. We will import the useState hook from React in the App component and also create the function called “increment” that will increase the count by 1 each time the button is clicked. We will pass both of these as props to the Button component:

App.tsx

Notice that if you pass anything that isn’t a number to setCount inside the increment function, React will yell at you. This is because we set the default value to the number 0 in our useState hook, so setCount only accepts values with the type of number for the count now.

If you want to make, for example, the count prop not be required to be passed down to the Button component, all you have to do is insert a “?” right after the variable name, like so:

This has been a very brief introduction to using TypeScript in React to help get you started. There is A LOT more to cover, so please be sure to check out the excellent resources linked below to continue your journey.

Thanks for reading — connect with me on LinkedIn and check out my portfolio at kylefarmer.dev, cheers!

--

--