Getting started with React and TypeScript

Amanda Fawcett
Apr 23, 2020
editor-page-cover

If you’re a React developer, you may have heard about TypeScript, the statically typed superset of Javascript that can make faster, more robust React apps. TypeScript and React work together to alleviate some of the drawbacks of React. Typescript’s sophisticated type system comes with a bit of a learning curve, so today we want to walk you through everything you need to know to get started. .

Today we will discuss:


Learn TypeScript for React with hands-on projects

Set up React projects with TypeScript using Create React App, Webpack, and Babel

Using TypeScript with React


Overview of Typescript with React

TypeScript is a superset of JavaScript, so any feature of JavaScript is also available in TypeScript. But, TypeScript takes JavaScript one step further and adds a powerful type system to enable code refactoring, navigation features, type checking, and more.

This powerful statically-typed language is great on its own, but it also does a lot for React developers. In fact, many React developers who adopt TypeScript say they can’t imagine their work without it.

In order to use Typescript with React, we need to have a sense of what Typescript does to our JavaScript code. While a full course on TypeScript is needed to get you up to speed, let’s look at what TypeScript adds to JavaScript code:

  • Type annotations: allow us to assigned types to variables
  • Type inference: infers the data type of a variable
  • The never type: used to represent a type of value that will never occur
  • The unknown type: allows us to reduce the use of any and create more strongly-typed code
  • Intersection types: allow us to combine existing types to form a new type with all the members from the type it is based on
  • Union types: allows us to combine a new form of type using the pipe | character
  • Make types reusable with generics
  • Strongly-typed arrays
  • Strongly-typed tuples

For a basic tutorial on Typescript, check our article TypeScript Tutorial: a step-by-step guide to learn Typescript


Benefits of using Typescript with React

You may still be wondering, “but why should I use Typescript for a React.js project?”. Let’s break down the benefits of Typescript and show how it makes frontend React development easier.

  • Code suggestions: Typescript offers suggestions and options while you type. This saves a lot of effort and makes it easier for a new developer to use your source code. These code suggestions prevent wasted time, ease team communication, and make your codebase more consistent.

  • Readability and validation: Since Typescript is a statically-typed system, you can add types to variables, functions, and properties, making your code far easier to read. Typescript also serves to eliminate React’s PropTypes, which makes React development easier.

  • Catch errors earlier and IntelliSense: One of the most loved features of Typescript is its ability to highlight errors as soon as they crop up. Typescript shows you errors before you ever run the code, saving hours of time fixing bugs or mistakes early on.

  • Accurate code maintenance and refactoring: As the codebase of a React app grows, it can become too difficult to read, share, or maintain. Navigating these codebases can be tedious, and refactoring code is risky. Typescript actually helps you refactor code and prevent typos, making it far easier to maintain and update without changing any of its behaviors.

  • Improves use of JavaScript: Typescript integrates fully with JavaScript and uses the newest features available to a JavaScript developer. React projects built with Typescript compile to a version of JavaScript that runs on any browser.

widget

How to use TypeScript with React

Now that you have a sense of what Typescript is and why you should use it, let’s dive a bit deeper into React development with TypeScript. I will show you four of the best features offered by TypeScript, but keep in mind that there is a lot more it can do from React.


1. Strongly-typed function component props

One of the best parts of using Typescript with React is the ability to use strongly-typed component props. This means you can more quickly know what a component passes to prevent mistakes in your app. To show you how it’s done, let’s create a React Hello component with a simple prop.

Take a look at the code below.

Here, props hasn’t been given a type, so Typescript will designate the any type. To solve this, we use type annotations for props. This can be done with a regular function as well as an arrow function.

Note: in React, function components are functions that take in a props parameter to return JSX.

We must add a type annotation for the props in our code. This will define a who prop. This makes Hello’s props strongly-typed.

const Hello = (props: { who: string }) => (
  <p>Hello, {props.who}</p>
);

There is, however, still an error where Hello is consumed.

We resolve this by passing a string ”Mary” into Hello.

render(<Hello who="Mary" />, rootElement);
We then shorted the `Hello` component by destructuring the `props` parameter 

const Hello = ({ who }: { who: string }) => (
  <p>Hello, {who}</p>
);

We can also refactor our Hello component to make it into a regular function instead of an arrow function.

function Hello({ who }: Props) {
 return <p>Hello, {who}</p>;
}

2. Strongly-typed context for functional components

React context is a tool that allows several components in the same tree to share data. This saves effort, as you don’t have to pass data down the tree via props. A context is commonly used to provide theme information, such as a color value, so that all components can access it. Let’s see how Typescript makes this easier by inferring the type for context.

TypeScript offers the powerful tool of inference, where the compiler can infer the type information even if none has been specified. This is very useful for strongly-typed contexts.

We start by creating a theme using the createContext function of React.

const defaultTheme = "white";
const ThemeContext = React.createContext(defaultTheme);

Now that we have the theme, we create a provider component.

type Props = {
  children: React.ReactNode
};
export const ThemeProvider = ({ children }: Props) => {
    const [theme, setTheme] = React.useState(defaultTheme);
 
    React.useEffect(() => {
        // We'd get the theme from a web API / local storage in a real app
        // We've hardcoded the theme in our example
        const currentTheme = "lightblue";
        setTheme(currentTheme);
    }, []);
 
  return (
    <ThemeContext.Provider value={ theme }>
      {children}
    </ThemeContext.Provider>
  );
};

What does this all do? The theme value is held in the state, so if it changes, the children have access to the new theme. We also use React’s useEffect hook to get the current theme and update the theme state value.

We can then create a custom hook that allows our function component to consume the context like this:

const useTheme = () => React.useContext(ThemeContext);

We can use the ThemeProvider component in the component tree. To give Header access to the context, we use the useTheme hook.

const Header = () => {
    const theme = useTheme();
    return (
        <div style={{backgroundColor: theme}}>Hello!</div>
    );
}

The type for a React context is correctly inferred if we provide a sensible default upon creation. You can extend this basic concept to more complex strongly-typed contexts or a strongly-typed class component.


3. Strongly-typed React event handlers

In React, interactive components are used to handle events, but how do we implement event handlers in a strongly-typed function component? Let’s learn how and see how Typescript type inference helps us along the way.

First, look at the following code:

This app contains an input that should allow a user to input search criteria, but right now, a user is not able to input anything. We need to add an onChange event handler inline to update the criteria state. Notice that IntelliSense is provided on the e parameter.

In React, the onChange event handler is the same as the JavaScript attribute onchange, but it is camel-cased.

<input
  type="text"
  value={criteria}
  onChange={e => setCriteria(e.currentTarget.value)}
/>

TypeScript has inferred the type, making the inline event handler strongly-typed. Now, with that event handler, a user can enter criteria into input. If we want to create a named event handler function, we must hover over the event handler prop to learn what the function parameter type should be. All thanks to TypeScript!


4. Strongly-typed refs in function components

React’s functional components are essential for writing modern React apps. React Hooks make it possible to write an entire application with React components. And with TypeScript, we can get a strongly-typed reference to an element in a function component. Let’s look at how it’s done.

We can use the useRef hook to access all properties and methods of an element, which is used to invoke methods imperatively. Look at this example:

const element = React.useRef(null);
// can access all the properties and methods of `element` via `element.current`
 
...
return (
  <SomeComponent ref={element} />
);

Currently, TypeScript infers the type of input.current as null if strict mode is on, and any if not. We can then define the type of the returned element by passing a generic type parameter in the useRef hook like this:

const element = React.useRef<ElementType>(null);

Remember: Strict mode is a React tool we can use to highlight potential problems in an application. It renders checks on our code.

This can also be done with class components using the createRef. We can explicitly define the type of element returned by passive a generic type parameter. This ensures that the reference is strongly-typed.

React.createRef<ElementType>();

There’s a lot more that TypeScript can do for react. The general rule of thumb is to make everything as strongly-typed as possible. This can apply to strongly-typed events, class props, class state, component states with useState, and much more.


Keep the learning going.

Learn TypeScript with React without scrubbing through videos or documentation. Educative’s text-based courses are easy to skim and feature live coding environments - making learning quick and efficient.

Using TypeScript with React



Creating a React project with TypeScript

There are two common ways to create a React project with TypeScript: using Create React App or manually. Today, I will show you how to use Create React App to make a basic React-Typescript project. If you’re curious about the manual process, check out Educative’s course Using Typescript with React for an easy-to-follow tutorial.


Step 1: Gather technical requirements

To set up a new React app with Typescript, you will need the following tools:

  • Node.js and npm. You will need at least version 5.2.
  • A code editor. I recommend Visual Studio Code.
  • Create React App (CRA)

Step 2: Set up React with Typescript

Create React App (CRA) is a command-line tool used to build React applications quickly. You can download CRA as a npm package using the npx command. If you are creating a new React app using create-react-app v2.1 or higher, Typescript is already built in. So, to set up a new project with Typescript, simply use --typescript as a parameter.

npx create-react-app hello-tsx --typescript

This creates a project called my-app, but you can change the name. It’s important to note that files containing JSX should be a .tsx file, and files that contain only Typescript code should be a .ts file.

The app’s root HTML file is in the public folder. It is called index.html. The React app is injected into index.html by following line of code:

ReactDOM.render(<App />, document.getElementById('root'));

This means that the root React component is called App, defined in App.tsx.

If you want to add TypeScript to an existing create-react-app project, you’ll need to install TypeScript and any required types. Check out this link to see how it’s done.

Before starting the server, you need to rename your files to .tsx or .ts. This generates the tsconfig.json file.


Step 3: Run the app

Now that you have the app ready to go, you can run it in development mode. Find the root folder of the project and run the start npm script in the Terminal.

cd my-app
npm start

Your root folder must have the same name as your app and contain the package.json file. You now have your React app ready to go with TypeScript!


What to learn next

Now you have a basic understanding of what Typescript is and what it has to offer for your React projects. There is quite a lot more that Typescript can do for React and so much more to learn! Next you’ll want to learn:

  • Create strongly-typed class components
  • React component props
  • Create a React TS project from scratch
  • Using Babel and Webpack
  • Add npm scripts
  • and more

Educative’s course Using TypeScript with React will get you started with these concepts and beyond. You’ll learn how to utilize TypeScript’s sophisticated type system to make React development faster. By the end, you’ll have two functioning React apps based on TypeScript.


Continue reading about React and TypeScript

WRITTEN BY

Amanda Fawcett