How to Use TypeScript with React
Using TypeScript with React, we get an excellent developer experience compared to what is provided by other frameworks. TypeScript can be helpful to React developers in a lot of ways.
TypeScript allows you to define complex type
definitions in the form of interfaces. This is helpful when you have a complex type
that you want to use in your app, such as an object which contains other properties. This results in strict checks which in turn reduces the amount of possible bugs that you might have produced without it.
The key to TypeScript is that it’s a statically typed script. Programming languages can either be statically or dynamically typed; the difference is when type checking occurs. Static languages’ variables are type checked, which also helps make the code more readable.
In this post, I will show you how to use TypeScript to improve the code of a React app by opening the syntax for self documenting code.
Tip: Use Bit to share and reuse React components between apps. You can discover and play with components, and install them to build faster. Try it.
Getting started with examples
Installation
Let’s start by creating a simple React Project using create-react-app
. In your command terminal, type:
$ create-react-app typescript-react
$ cd typescript-react
This command will create a new React project directory named typescript-react
in your folder. Let’s make some changes inside this project so that we can use TypeScript.
Let’s start by installing a couple of packages as dependencies to this project. Along with things like webpack
and webpack-dev-server
, we also need to install the typescript
package and TypeScript specific modules like @types/react
and @types/react-dom
. We also need the ts-loader
for webpack.
$ yarn add webpack webpack-cli webpack-dev-server typescript @types/react @types/react-dom ts-loader
Configuration
Open the project directory in a code editor that supports TypeScript (I ❤️ VS Code) and take a look at the package.json
file. Rewrite the scripts
objects as shown below:
"scripts": {
"build": "webpack ./webpack.config.js",
"start": "webpack-dev-server ./webpack.config.js --content-base ./public"
}
Here, the start
script uses the webpack.config.js
file to run the webpack-dev-server
for live application development and serves up the ./public
folder. Create this file inside the root of the directory and write the following code inside it:
module.exports = {
devtool: 'inline-source-map',
entry: './src/app.tsx',
output: {
path __dirname + '/public',
filename: 'build/app.js'
},
resolve: {
extensions: ['.ts', '.tsx', '.js']
},
module: {
rules: [
{test: /\.tsx?$/, loader: 'ts-loader'}
]
}
}
Here, inline-source-map
is used to debug TypeScript files within the browser. ./src/app.tsx
is specified as the entry point. I’ve also specified a location for the built bundle inside the output
object. We also need to inform webpack that it needs to support all files that have a .ts
, .tsx
or .js
extension. Finally, we need to tell webpack to use ts-loader
for .ts
and .tsx
files.
Inside the public
folder, delete everything except the index.html
file. Rewrite the code inside this file as shown below:
<!DOCTYPE html>
<html lang="en">
<body>
<div id="root"></div>
<script src="./build/app.js"></script>
</body>
</html>
This code has a simple div
with an id
of “root” where we will render the React app, and then loads the bundle that is generated by the webpack.
Next, let’s write some configuration for TypeScript. Create a tsconfig.json
file inside the root of the directory and write the following code inside it:
{
"compilerOptions": {
"sourceMap": true,
"module": "commonjs",
"target": "es5",
"jsx": "react"
},
"include": [
"src"
],
"compileOnSave": false
}
The sourceMaps
is enabled in order to debug the TypeScript files within the browser. We also need to tell TypeScript that we are using commonjs
for the module format targeting es5
. But most important piece of code here is the one that tells jsx
to transpile to React.createElement
. After that we need to tell TypeScript that the source code is present inside the src
folder. Disable TypeScript
‘s compileOnSave
because that will be handled by webpack.
Verify
Delete all the files inside the src
folder and create a new file named app.tsx
with the following code inside it:
import * as React from 'react';
import * as ReactDOM from 'react-dom';ReactDOM.render(
<div>Use TypeScript with React</div>,
document.getElementById('root')
);
Run the start
script using NPM or Yarn. This will start up webpack’s development server and serve the public
folder at localhost:8080
.
Stateless React Components in TypeScript
Writing stateless React components in TypeScript is simple. Open the app.tsx
file inside the src
folder and move the div
inside the render
function to a stateless component.
import * as React from 'react';
import * as ReactDOM from 'react-dom';const App = () => <div>Use TypeScript with React</div>;ReactDOM.render(
<App />,
document.getElementById('root')
);
By using components, we can leverage props
to change the component’s behavior. Pass a prop
named message
to the App
component and use it inside the function body.
const App = ({message}) => <div>{message}</div>;
TypeScript will now give us an error saying that the message
prop needs to be provided. To resolve this error, re-write the render
function as follows:
ReactDOM.render(
<App message="Use TypeScript with React"/>,
document.getElementById('root')
);
This works great for stateless functions. We can take this a step further and annotate this function as React.SFC
. Re-write the App
component as follows:
const App: React.SFC<{message: string}> = ({message}) => <div>{message}</div>;
And you can also take the inline prop type definition and move it into a type
:
type AppProps = {message: string}
const App: React.SFC<AppProps> = ({message}) => <div>{message}</div>;
Stateful React Components using TypeScript
To create a stateful component in React, we need to extend the React.Component
class. This class takes two generic parameters, props
and state
.
Open the app.tsx
file inside the src
folder and re-write the App
component as a stateful component as shown below:
class App extends React.Component {
render() {
return(
<div>Use TypeScript with React</div>
);
}
}ReactDOM.render(
<App />,
document.getElementById('root')
);
Similar to stateless components, we can use props
to change the behavior of the component. React.Component
takes the props
as its first argument:
class App extends React.Component <{
message: string
}> {
render() {
return (
<div>{this.props.message}</div>
);
}
}ReactDOM.render(
<App message="Use TypeScript with React"/>,
document.getElementById('root')
);
Such components which extend React.Component
are called stateful because they can have their own internal state. React.Component
takes a second generic argument that specifies the type of the state.
class App extends React.Component <{
message: string
}, {
count: number,
}> {
constructor(props) {
super(props);
this.state = {
count: 0
}
}
render() {
return(
<div>{this.props.message}{this.state.count}</div>
);
}
}
Here, I’m creating a state called count
of type number
. This state is then initialized inside the constructor
. We can then use this state in other places, like the render
method.
The main reason for having a local state in a component is that you get to manage it inside the component. Inside the App
component, create a new function called increment.
increment = () => {
this.setState({
count: this.state.count + 1
});
}
Call this function on the div
that is inside the components render
function.
render() {
return (
<div onClick={this.increment}>{this.props.message}{this.state.count}</div>
The state will now change whenever the user click on the div
that is rendered on the browser.
Conclusion
In this post, you saw how TypeScript can be used to make the code of our React apps more maintainable and readable.
- We started with learning about the packages that are required to make TypeScript compatible with React.
- You then saw how to configure TypeScript to accept React code, and how to configure Webpack to render this code on a browser.
- Finally, we learned how to write simple stateless and stateful React Components with TypeScript.