Read about TypeScript with React in about 13 minutes Using free translation
This article is based on a talk I gave at React JS & React Native Bonn Meetup in the past. The purpose of the article is to answer the following questions:
- What is TypeScript?
- How to use TypeScript in React?
- Why should we (not) use TypeScript?
This is my first public speech outside of school, and it’s great to finish it off. Thank you all for coming! 😁 public speaking is something I like very much and I hope to make more speeches in the future.
What is TypeScript?
Typescriptlang.org explains TypeScript (TS for short) as follows:
TypeScript is a superset of JavaScript types that can be compiled to pure JavaScript.
The above description can be interpreted as:
- TypeScript is a type language associated in some way with JavaScript. The main difference is that TypeScript is a statically typed language while JavaScript is dynamically typed.
- TypeScript can be compiled to pure JavaScript and executed in environments such as browsers or Node.js.
- Being a superset of JavaScript means that TypeScript only adds new features to JavaScript while remaining strictly compatible with the underlying JS specification.
For one thing, since TS is a superset of JS, the following code is valid for both languages:
function add(a, b) {
return a + b;
}
const favNumber = add(31.11);
Copy the code
We have seen that TS is special in its type system. If we add a type declaration to the above code, we will get the following TS code, but not JS code:
function add(a: number, b: number) :number {
return a + b;
}
const favNumber: number = add(31.11);
Copy the code
By adding these annotations, the TypeScript compiler can examine your code for code-level bugs. For example, it might find mismatched parameter types, or out-of-scope calls, and so on.
Compiling TypeScript with the TSC command-line tool goes through: type checking of code -> all checks pass -> pure JavaScript output. The output code is similar to the source code, except that there are no type annotations.
TypeScript also supports basic type inference, which simplifies code by omitting the type of a function return value and, in most cases, the type of variable assignment:
function add(a: number, b: number) {
return a + b;
}
const favNumber = add(31.11);
Copy the code
(The difference from the previous code is that the function return value has no type annotation.)
The basic types available in TS are Boolean, string, number, Symbol, NULL, undefined, and BigInt. There is also a void type, which means the function does not return anything; There are also Function types, and, typically, Array
for string[] or number[], variables that need to annotate the Array content type. There are also types like ReactElement, HTMLInputElement, and Express.app that are only valid in a specific deployment environment or with specific dependencies.
The most interesting thing about TS is that you can define your own types. Let’s look at some ways to model your domain. The first is to define your object using the interface keyword:
interface User {
firstName: string;
lastName: string;
age: number;
state: UserState;
}
Copy the code
You can also define enums:
enum UserState {
ACTIVE,
INACTIVE,
INVITED,
}
Copy the code
TypeScript even supports inheritance:
interface FunkyUser extends User {
isDancing: boolean;
}
Copy the code
TypeScript also has many advanced types, such as associative types, which can be used instead of enumerated types. The difference is that they are written more like JavaScript.
type UserState =
"active" |
"inactive" |
"invited";
const correctState: UserState = "active"; / / ✅
const incorrectState: UserState = "loggedin"; / / ❌ TypeError
Copy the code
For type checking, TypeScript doesn’t check the stereotype chain or other inherited methods. It only checks the type identifier of the property and the properties that handle the object:
const bugs: User = {
firstName: "Bugs",
lastName: "Bunny",
age: "too old".// TypeError: expected `number` but got `string`
state: UserState.ACTIVE,
}
Copy the code
You can certainly use class in TypeScript, and I’m not telling you to stay away from it, but be warned: I’ll explain why you don’t need it later. Look at this chestnut:
class JavaLover implements User {
private firstName: string;
private lastName: string;
private age: number;
private state: UserState;
getOpinion() {
return [ "!!!!! JAVA! 1!"]; }}Copy the code
Now that we’ve looked at some basic TypeScript code to get an idea of what it does, let’s look at how it works in React.
How to use TypeScript in React?
Because Babel 7 supports TypeScript built-in, it’s easy to integrate it into your build process. I still recommend checking out the build tool documentation, most of which contains well-written instructions on TypeScript Settings.
After configuring the build process, you can use TypeScript in your components. Here is a simple React-Native component that takes a TodoItem and a callback function and displays a Todo message.
import * as React from "react";
import { View, Text, CheckBox } from "react-native";
interface TodoItem {
id: string;
name: string;
isCompleted: boolean;
}
interface TodoListItemProps {
item: TodoItem;
onComplete: (id: string) = > void;
}
function TodoListItem(props: TodoListItemProps) {
const { item, onComplete } = props;
return (
<View>
<Text>{item.name}</Text>
<CheckBox isChecked={item.isCompleted} onClick={state= >{ onComplete(item.id); }} / ></View>
);
}
Copy the code
Because React is essentially pure JavaScript, it can be written as pure JavaScript. You only need to define the props structure of your component using the interface (see the Interface definition of TodoListItemProps), and define the types of component props parameters using the TodoListItemProps type just defined. You do not need to specify the return type (which is actually of type jsX.Element), because you can infer this from the type of the expression returned by the component.
Even if JSX is not part of the JavaScript specification, TypeScript can still type check it, which allows it to validate props in incoming components.
You can also use TypeScript with the React Class API:
import * as React from "react";
interface TimerState {
count: number;
}
class Timer extends React.Component<{}, TimerState> {
state: TimerState = {
count: 0
}
timerId: number | undefined = undefined;
componentDidMount() {
this.timerId = setInterval(
(a)= > {
this.setState(
state= > ({
count: state.count + 1})); },1000
);
}
componentWillUnmount() {
if (this.timerId) {
clearInterval(this.timerId);
}
}
render() {
return (
<p>Count: {this.state.count}</p>)}}Copy the code
When you write a class, you pass the type arguments to the react.component that you extend. The first is the props ({} empty object) in the previous example component; The second generic type argument is the component’s state, which in this case is a count field containing only numeric types. Here you will find using the initialized to undefined instance fields timerId, which is why its type is declared number | undefined, which means that it can be a number or undefined type.
As you can see, using TypeScript with React is simple and requires no ritual. Basically, it is a more powerful alternative to prop-types because it supports more advanced types and can also use plain JS code. Also, TypeScript provides compile-time validation, whereas prop-types is only available in development environments.
If you want to tinker with some code yourself, take a look at the examples I used in my live demo. It’s in the REPo’s todo folder: github.com/Skn0tt/reac… .
Why should we (not) use TypeScript?
So far, I’ve assumed that you have a general understanding of what TypeScript is and what it can do. So I’ll go on to explain why we don’t use TypeScript.
Reasons not to use TypeScript
TypeScript isn’t a new way of writing JavaScript, it just extends JavaScript’s ability to write type annotations. First and foremost, TypeScript is a type checker, but there seems to be a tendency to ignore this fact, as I’ve seen recently:
“TypeScript is so great that we can finally do Java development in a front-end environment.”
It seems to make sense, but it’s actually harmful. Sure, Java developers are used to nice features like type systems, classes, interfaces, etc., but TypeScript still appeals to them. However, if Java (or other languages heavily influenced by object-oriented programming) developers switch to TypeScript without understanding the deep-rooted differences between Java and JavaScript, that can be problematic. Remember: whether your JavaScript code is compiled with TypeScript or not doesn’t change its runtime behavior. Once it runs, it no longer has type information, which is both its strength and its pain point. JavaScript’s ability to dynamically type and enforce typing through prototype-chain inheritance gives it a lot of new functionality and features that aren’t far behind Java. Keep this in mind as you transition from Java development to TypeScript development.
Why and how does TypeScript still help me?
Adding type annotations to your project is a great way to document the structure of your code, providing a way to structure the data you pass around. TypeScript is also “machine readable,” which means it can be executed by machines! This provides great editor support (try VS Code, it’s a disaster!). This simplifies code refactoring and enhances static security checks.
TypeScript doesn’t just allow you to document code structures; it forces you to do it. It makes you stop and review the code you’re writing and wonder if you can create a clearer code structure to achieve higher code quality.
Writing type annotations makes my code easier to understand, at least for me, because I can understand the structure of the data without delving into the project, and it removes a lot of cognitive complexity.