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:
Try one of our 300+ courses and learning paths: Using 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:
any
and create more strongly-typed code|
characterFor a basic tutorial on Typescript, check our article TypeScript Tutorial: a step-by-step guide to learn Typescript
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.
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.
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>;
}
Enjoying the article? Scroll down to sign up for our free, bi-monthly newsletter.
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.
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!
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.
Try one of our 300+ courses and learning paths: Using TypeScript with React.
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.
To set up a new React app with Typescript, you will need the following tools:
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.
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!
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:
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.
Free Resources