25

React TypeScript: Basics and Best Practices

 4 years ago
source link: https://blog.bitsrc.io/react-typescript-cheetsheet-2b6fa2cecfe2
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

An updated handbook/cheat sheet for working with React.js with TypeScript.

M7JJZvm.jpg!web

There is no single “right” way of writing React code using TypeScript. Just as with other technologies, if your code compiles and works, you probably did something right.

That being said, there are “best practices” that you do want to consider following, especially when writing code others will have to either read or re-use for their own purposes .

So, here I’m going to list some useful code-snippets that follow said “best practices”. There are a lot of them, some that you might’ve used already in the past and some that might be new. Just go through the list and make mental notes. Bookmarking this article for future reference might be a good idea as well.

Making your components ready for sharing, with TypeScript

uyM3Ejm.jpg Example: browsing through shared React components in bit.dev

Bit.dev has become a very popular alternative to traditional component libraries as it offers a way to “harvest” and share individual components from any codebase (to a single component hub).

By building projects using React with TS, you make sure your components are easily comprehensible to other developers (as well as to your future self). That is absolutely crucial for making them ready for sharing. It’s a great way to write maintainable code and optimize your team collaboration.

Learn more about sharing and reusing React TS components across repos here :

Getting started

create-react-app with TypeScript

$ npx create-react-app your-app-name --template typescript

If you’re more of a fan of Yarn, you can use the following command:

$ yarn create react-app your-app-name --template typescript

In either case, notice how we’re not directly using the app, rather, we’re using other tools that will download the latest version of the app whenever it’s required. This helps ensure you’re not using an outdated version.

Basics

Some of the very interesting tidbits added by TS to the language are:

Interfaces

One of the many benefits TypeScript brings to the table, is access to constructs such as this, which allows you to define the interface of your components or even any other complex objects you might want to use with them, such as the shape your Props object will have (i.e how many properties and their types).

The above code ensures that whoever uses your components needs to add exactly 3 properties:

  • text: which needs to be a String
  • type: which needs to be a ButtonType option (I’ll cover Enums in a second)
  • action: which is a simple function

If you ignore one of them or send something that’s not compatible, both the TypeScript compiler and your IDE (assuming you’re using a JavaScript specific IDE, such as Code) will notify you and won’t allow you to continue until you fix it.

Enums

Just like with Interfaces, Enums allow you to define a set of related constants as part of a single entity.

And you can see how to import the Enum and use it here:

Please note that unlike Interfaces or Types, Enums will get translated into plain JavaScript. So, for example, this:

enum SelectableButtonTypes {Important = "important",Optional = "optional",Irrelevant = "irrelevant"}

will transform into this:

"use strict";var SelectableButtonTypes;(function (SelectableButtonTypes) {SelectableButtonTypes["Important"] = "important";SelectableButtonTypes["Optional"] = "optional";SelectableButtonTypes["Irrelevant"] = "irrelevant";})(SelectableButtonTypes || (SelectableButtonTypes = {}));

Interfaces vs Types alias

A common question when it comes to newcomers to TypeScript is whether they should be using Interfaces or Type Aliases for different parts of their code, afterall, the official documentation is a bit unclear regarding that topic.

Truth is, these concepts although conceptually different, in practice are pretty much the same:

  1. They can both be extended.

2. They can both be used to define the shape of objects.

3. They both can be implemented in the same way.

The only extra feature Interfaces bring to the table that Type aliases don’t, is “ declaration merging” which means you can define the same interface several times and with each definition, the properties get merged:

Optional types for your props

Part of the benefits of using Interfaces is that you’re able to enforce the properties of your props for your components. However, thanks to the optional syntax available through TypeScript, you can also define optional props, like this:

Hooks

Hooks in general are the new mechanic React provides to interact with several of its features (such as the state) without requiring to define a class.

Adding type check to hooks

Hooks such as useState receive a parameter and correctly return the state (again, that’s for this case) and a function to set it.

Thanks to TypeScript’s type validation, you can enforce the type (or interface) of the initial value of the state, like this:

Nullable values to hooks

However, if your initial value for the hook can potentially be null then the above example will fail. For those cases, TypeScript allows you to set an optional type as well, making sure you’re covered from all sides, like so:

That way you’re ensuring you keep type checks, but allow for those scenarios where the initial value can come as null .

Generic Components

Just like you can define generic functions and interfaces in TypeScript, you can define generic components, allowing you to re-use them for different data types. You can do this for props and states as well.

You can then use the component either by taking advantage of type inference or directly specifying the data types, likes so:

Type inference example
Directly declared types

For the latter, note that if your list contained strings instead of numbers, TypeScript would’ve thrown an error during the transpilation process.

Extending HTML Elements

Sometimes, your components are nothing but already existing HTML elements on steroids, like a “borederd box” (which is simply a component that always renders a div with a default border) or a “big submit” (which again, is nothing but your good old submit button with a default size and maybe some custom behavior).

For those scenarios, creating the component all by yourself, without any type of connection to the original HTML one means you’ll need to manually define every single HTML property the element can receive (that is, of course, if you´re trying to do it right).

Instead of that manual labor, you can extend HTML’s properties and use that to define your own set of props:

As you can see, I’ve extended HTML’s default props and added a new one: “title” for my custom needs.

Event Types

As you probably know, React provides its own set of events, which is why you can’t directly use the good old HTML Events. That being said, you do have access to all the useful UI events you need, so much so in fact, that they have the same names as well, so make sure you reference them directly like React.MouseEvent or just remember to import them from React like so:

import React, { Component, MouseEvent } from 'react';

The benefits of using TypeScript here, is that we can also use Generics (like in the previous example) to restrict the elements a particular event handler can be used on.

For example, the following code will not work:

And you’ll see an error message similar to the following:

z26bmmy.png!web

You can, however, use unions to allow a single handler to be re-used by multiple components:

Integrated type definition

Finally, for the last tip, I wanted to mention the index.d.ts and the global.d.ts files. They’re both installed when you add React to your project (if you used npm, you’ll find them inside the npm_modules/@types folder.

These files contain type and interface definitions used by React, so if you need to understand the props of one particular type, you can simply open these files and review their content.

For example:

MBfMrye.png!web

There you can see a small section of the index.d.ts file, showing the different signatures for the createElement function.

Conclusion

There is a lot more you can achieve by using TypeScript as part of your React toolchain, so if you saw at least one snippet that you liked here, consider reading up on how to gradually migrate your React projects to TypeScript or even learn how to design your own React TypeScript libraries here.

Either way, I hope you got something out of this article, and feel free to leave any other tips or tricks you’ve picked up over the years of using TypeScript for your React projects!

See you on the next one!


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK