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.
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.
Use the
React.SFC
type when defining functional componentsconst MyComponent: React.SFC = () => (<div>Hello!</div>)
The
SFC
(short for stateless functional component) defines a function type that returns a JSX Element.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'
Use the
React.CSSProperties
type when defining style objectsconst myStyle: React.CSSProperties = { backgroundColor: 'red', border: '1px solid black' } const MyComponent: React.SFC = () => <div style={myStyle}>Hello</div>
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:
- The type of event (whose types you can find here)
- 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.