I’m Building An App – Step 5 – Typescript

This is the seventh post in a series of posts which will illuminate my journey to becoming a Full-Stack JavaScript Developer. Read the first one here.

Recap

My plan is to progressively enhance the app into a fully complete app, allowing me to step-by-step learn important principles of development without overwhelming myself while at the same time practice my learning by applying them to a real app.

JavaScript the Dynamic Language

JavaScript is considered to be a weakly-typed, dynamic language. A dynamic language refers to the way variables and functions are initialized while a weakly-typed language has “looser typing rules and may produce unpredictable results or may perform implicit type conversion at runtime”.

When you declare a variable in JavaScript, you don’t need to state the variable type, it’s implicitly determined by the programming language. What’s more, the variable type can change based on reassignment.

An Example

Let’s say I have built a shopping cart app in JS and the app has a variable named price to record the cost of a single product. I need to not only be able to record and display this price but perform math operations with it(sum up the prices to make a Shopping Cart total, for instance).

When I first initialize the price variable I set it to a floating point number value of 9.99. I did not specify that it was a floating point number; JavaScript figured that out for me.

Later on, I need to display this price on the front-end and I hastily enter the price as a string of text. The JavaScript engine says, Cool, I guess this is a string now.

Why would I do this? Perhaps I need to prepend the currency symbol($) to the price and I can’t do that with a number.

var price = 9.99
console.log(typeof(price))  // number
price = "$9.99"
console.log(typeof(price))  // string

The Problem

Now if I try to perform math operations on the price it’s going to fail as it’s now a string.

This super simple example should hopefully illustrate one of the pitfalls of a dynamic language and this type of implicit type conversion is one of the biggest causes of bugs in dynamic language applications.

Sure, it’s easy enough to notice the bug in our example but imagine the application has dozens of files and thousands of lines of code. Keeping track of all of the variables and their types in your head becomes impossible so it would be nice to have a tool that helped avoid the aforementioned pitfall.

A Possible Solution

Typescript is a superset of the JavaScript language which offers things like static checking and code refactoring when developing JavaScript applications. When you write Typescript it is later compiled into clean JavaScript code.

Basically, it makes your JavaScript look like more like a strongly-typed and static language resembling something more like Java or C#.

New Projects

There isn’t a single initialization command for adding Typescript to your React Native app, however, specific instructions can be found here. I won’t bother going through them in this post. I can say that it was relatively easy and took just a few minutes.

The Plan

The nice thing about Typescript is that we don’t have to convert the entire project immediately to Typescript in order for our app to run. We can convert one file at a time into Typescript and slowly clean up our app in a measured fashion.

What’s more, Typescript files can be just plain JavaScript, meaning that we could simply rename our .JS(or .JSX) files into .TS(or .TSX) and they would compile fine without actually adding any Typescript.

With that in mind, we can convert our app piece by piece(or atleast, the major components) to Typescript at our own pace. We’ll start with the main entry path to the app, App.js.

App.js

The first thing to do is to rename the file to App.tsx. Technically, Typescript uses .ts as the file extension but we’re using some type hinting here to indicate that we’re not writing pure JS but JSX. It’s the same reason that we would previously have our file named App.jsx.

Interfaces

If you do nothing else other than apply interfaces to your React components you would still be improving your React code quite a bit.

An interface is like a predefined shape for a structure which says, this is how this thing should look. We determine beforehand the logical shape of this structure so that it is stable. If we fail to build our structure to match the shape of the interface we will get an error. If we try to change the shape of the structure later we will get an error.

The two things you absolutely need to apply interfaces to are a component’s state and props. Here’s a super easy example from the main App.tsx file:

interface State {
  isLoadingComplete: boolean
}

interface Props {}

export default class App extends React.Component<Props, State> {
  state = {
    isLoadingComplete: false,
  }
}

My main App file has just a single piece of state which tracks whether or not loading is complete. If it’s not finished loading a loading spinner component is rendered; if it’s finished loading the rest of the app is rendered.

It doesn’t have any props.

What we’ve done in the example above is set the shape of our props and state for our App component. The following will cause an error in our IDE if we fail to maintain that shape:

  • If we pass any props to this component(because none are declared in the interface).
  • If we declare any new props on the state object other than isLoadingComplete.
  • If we change isLoadingComplete to anything other than boolean.
  • Leaving out any piece of the interface object when passing props to the component(if the Props object was not empty).
  • If any piece of the Props interface did not match the declared variable type(again, if the Props object was not empty).

It’s Just a Tool

One thing to keep in mind with Typescript is that it will still compile your code into JavaScript if it catches errors. If there are no actual JavaScript errors the code will still run; TypeScript doesn’t prevent compiling your app if you leave out a prop or mutate a piece of state. It’s meant to warn you of potential issues with your code.

Typescript is really a helper tool for development teams to write better code by providing warnings when our code is not taking the shape we initially agreed it would or when we return a different variable type from a function than we initially said we would. It helps us understand our code better and know what our variables should be and how our functions should act.

There are too many files that need to be converted in this app to go over here but the idea is generally the same for all of the files:

  • Create interfaces for our Props and State.
  • Assign a type to our variables.
  • Specify the return type for our functions.

Next

In order to speed up this app as well as add some offline compatibility we’ll be adding some sort of caching to the app in the next blog post.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s