Typescript and React are a great combination. Typescript allows you to define strict types for your React components, their props and states, as well as event handlers.

In this post, we’ll go through the fastest way to get started with React and Typescript, and some tips and tricks for using them together.

banner image

Setting up a new project

In my opinion, this is the most frustrating part when working with new javascript stacks. With the plethora of options available it’s always hard to decide which tools to use, and harder still to integrate them together.

For React and Typescript though, we can piggy-back on the success of the most popular React starter project: create-react-app. To create a new project, install the create-react-app CLI:

npm install -g create-react-app

Then run the command:

create-react-app my-app --scripts-version=react-scripts-ts

And thats it! This command will create your React application, bundled with Typescript, inside a folder called my-app. To start the application, go inside the my-app folder and run the npm start command.

Using React’s type definitions

React has many useful type definitions which can be used in your application. These should be used everytime you want to create a new React component.

  1. Use the React.SFC type when defining functional components

    const MyComponent: React.SFC = () => (<div>Hello!</div>)
    

    The SFC (short for stateless functional component) defines a function type that returns a JSX Element.

  2. Use the React.ReactChild return type if you want to allow other renderable elements, like strings or numbers

    // This is not allowed
    const MyComponent: React.SFC = () => 'Hello'
    
    // This is allowed
    const OnlyRenderable = (): React.ReactChild => 'Hello'
    
  3. Use the React.CSSProperties type when defining style objects

    const myStyle: React.CSSProperties = {
        backgroundColor: 'red',
        border: '1px solid black'
    }
    
    const MyComponent: React.SFC = () => <div style={myStyle}>Hello</div>
    
  4. Using class based components doesn’t require any additional type definitions. Typescript infers the type from the inherited React.Component class definition.

    class MyComponent extends React.Component {
       // The React.Component type is inferred
    }
    

Defining types for props and state

Perhaps the most powerful feature of Typescript, is that it helps you get rid of React’s PropTypes entirely. You can now assert your prop types completely in Typescript. As an example, let’s create a prop interface for our React component, which has a single name attribute:

interface MyComponentProps {
  name: string
}

We can now assert the prop type for our component by using our interface as a type variable in the React.SFC type:

const MyComponent: React.SFC<MyComponentProps> = ({ name }) => {
  return <div>Hello {name}</div>
}

We can add prop and state types similarly for class based components:

interface MyComponentState {
  // ...
}

class MyComponent extends React.Component<MyComponentProps, MyComponentState> {
      render() {
        return <div>Hello {this.props.name}</div>
      }
}

Defining event handlers for elements

The React type library has type declarations for different event handler types as well. An event handler type definition depends on two factors:

  1. The type of event (whose types you can find here)
  2. The type of element being interacted with (whose types you can find here)

If we were to add on onClick event handler to our div element, the element type would be HTMLDivElement, and the event type would be React.MouseEventHandler, so our resultant code would look like this:

class MyComponent extends React.Component<MyComponentProps> {
  public myHandler: React.MouseEventHandler<HTMLDivElement> = (e) => {
    // do something
  }
  public render () {
    return <div onClick={this.myHandler}>Hello {this.props.name}</div>
  }
}

If you want to see the list of event attribute types and what events they map to, you can find it here

Going forward

Although this post hasn’t covered all of the different types that React provides, it should be enough to get you going for all but a few special cases. If you do have some extra time on your hands, it’s always useful to study all the types that you can use, which you can find in the source files.

If you’d like to look at a sample application built using this setup, you can take a look at the source code, and demo for a JSON Viewer tool that I built.

Overall I have found that integrating Typescript into my workflow has greatly increased my productivity. This is in part because of the great autocomplete suggestions that come with any IDE that supports Typescript, and also because of the consistency and type safety that it enforces.