This post goes through some of the benefits of using TypeScript with React apps which ultimately allow us to build our apps faster.
TypeScript is awesome. So is React. Let’s use them both together! Using TypeScript allows us to get the benefits of IntelliSense, as well as the ability to further reason about our code. As well as this, adopting TypeScript is easy as files can be incrementally upgraded without causing issues throughout the rest of your project.
Let’s start off by creating a new React project and integrate TypeScript. Run the following commands to initiate the project:
# Make a new directory
$ mkdir react-typescript
# Change to this directory within the terminal
$ cd react-typescript
# Initialise a new npm project with defaults
$ npm init -y
# Install React dependencies
$ npm install react react-dom
# Make index.html and App.tsx in src folder
$ mkdir src
$ cd src
$ touch index.html
$ touch App.tsx
# Open the directory in your favorite editor
$ code .
You can also see more courses : GraphQL with React: The Complete Developers Guide
We can then make an index.html
file with the following:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>React + TypeScript</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<div id="main"></div>
<script src="./App.tsx"></script>
</body>
</html>
We’ll be using Parcel as our bundler, but you can elect to use webpack or another bundler if you wish. Or, check this section if you prefer using Create React App. Let’s add Parcel to our project:
# Install Parcel to our DevDependencies
$ npm i parcel-bundler -D
# Install TypeScript
$ npm i typescript -D
# Install types for React and ReactDOM
$ npm i -D @types/react @types/react-dom
We can update our package.json
with a new task that will start our development server:
{
"name": "react-typescript",
"version": "1.0.0",
"description": "An example of how to use React and TypeScript with Parcel",
"scripts": {
"dev": "parcel src/index.html"
},
"keywords": [],
"author": "Paul Halliday",
"license": "MIT"
}
We can now populate a Counter.tsx
file with a simple counter:
import * as React from 'react';
export default class Counter extends React.Component {
state = {
count: 0
};
increment = () => {
this.setState({
count: (this.state.count + 1)
});
};
decrement = () => {
this.setState({
count: (this.state.count - 1)
});
};
render () {
return (
<div>
<h1>{this.state.count}</h1>
<button onClick={this.increment}>Increment</button>
<button onClick={this.decrement}>Decrement</button>
</div>
);
}
}
Then, inside of App.tsx
, we can load the Counter:
import * as React from 'react';
import { render } from 'react-dom';
import Counter from './Counter';
render(<Counter />, document.getElementById('main'));
Our project can be ran with $ npm run dev
and accessed at <a href="http://localhost:1234" target="_blank">http://localhost:1234</a>
.
If you’d rather use Create React App to initiate your project, you’ll be pleased to know that CRA now supports TypeScript out of the box.
Just use the --typescript
flag when invoking the create-react-app
command:
$ create-react-app my-new-app --typescript
Stateless or functional components can be defined in TypeScript like so:
import * as React from 'react';
const Count: React.FunctionComponent<{
count: number;
}> = (props) => {
return <h1>{props.count}</h1>;
};
export default Count;
We’re using React.FunctionComponent
and defining the object structure of our expected props. In this scenario we’re expecting to be passed in a single prop named count
and we’re defining it in-line. We can also define this in other ways, by creating an interface such as Props
:
interface Props {
count: number;
}
const Count: React.FunctionComponent<Props> = (props) => {
return <h1>{props.count}</h1>;
};
Class components can similarly be defined in TypeScript as such:
import * as React from 'react';
import Count from './Count';
interface Props {}
interface State {
count: number;
};
export default class Counter extends React.Component<Props, State> {
state: State = {
count: 0
};
increment = () => {
this.setState({
count: (this.state.count + 1)
});
};
decrement = () => {
this.setState({
count: (this.state.count - 1)
});
};
render () {
return (
<div>
<Count count={this.state.count} />
<button onClick={this.increment}>Increment</button>
<button onClick={this.decrement}>Decrement</button>
</div>
);
}
}
We can also define defaultProps
in scenarios where we may want to set default props. We can update our Count example to show this:
import * as React from 'react';
interface Props {
count?: number;
}
export default class Count extends React.Component<Props> {
static defaultProps: Props = {
count: 10
};
render () {
return <h1>{this.props.count}</h1>;
}
}
We’ll need to stop passing this.state.count
in to the Counter
component too, as this will overwrite our default prop:
render () {
return (
<div>
<Count />
<button onClick={this.increment}>Increment</button>
<button onClick={this.decrement}>Decrement</button>
</div>
)
}
You should now have a project that’s set up to use TypeScript and React, as well as the tools to create your own functional and class-based components!
#reactjs #typescript #web-development