Why use static types in JavaScript? (Part 1)
Tags: javascript, types, flow
Published: 2016-12-08 18:36:48

---
title: Why use static types in JavaScript? (Part 1)
published: true
description: Types are bound to improve your JavaScript, if you're willing to spend some time looking at their advantages.
cover_image: http://i.imgur.com/WPQOAPu.png
tags: javascript, types, flow
---

## Intro

As JavaScript developers, we don't encounter static types that often.

Does that mean they aren't important? Nope.

Understanding types isn't just a mind-expansion exercise either. They're bound to improve your JavaScript, if you're willing to spend some time looking at their advantages, disadvantages, and use cases.

Interested? Well, you're in luckâ€Š–â€Šthat's what the rest of this post is about!

## First, a definition

The quickest way to understand static types is to contrast them with dynamic types. A language with static types is referred to as a **_“statically-typed language”_**. On the other hand, a language with dynamic types is referred to as a **_“dynamically-typed”_** language.

The core difference is that **statically-typed** languages perform type checking at **compile time**, while **dynamically-typed** languages perform type checking at **runtime**.

This leaves one more concept for us to tackle: what does “type-checking” mean?

To explain, let's look at types in Java vs. Javascript.

“**Types**” refers to the type of data being defined.

For example, in Java, if you define a `boolean` as:

`boolean result = true;`

This has a correct type, because the `boolean` annotation matches the value given to `result`, as opposed to an integer or anything else.

On the other hand, if you tried to declare:

`boolean result = 123;`

This has an incorrect type, because it explicitly marks `result` as a `boolean`, but then defines it as the integer 123.

However, JavaScript and other dynamically-typed languages have a different approach, allowing the context to establish what type of data is being defined:

`var result = true;`

Long story short: statically-typed languages require us to declare the data types of our constructs before we use them, while dynamically-typed languages do not. JavaScript implies the data type, while Java states it outright.

So as you can see, types allow us to specify program invariants, or the logical assertions and conditions under which the program will execute.

**Type-checking** simply verifies and enforces that the type of a construct (constant, boolean, number, variable, array, object) matches the invariant that we've specified. We might, for example, specify that “this function always returns a string.” When the program runs, we assume that it will return a string.

The differences between static type checking and dynamic type checking matter most when a type error occurs. In a statically-typed language, type errors occur during the compilation step, i.e. at compile time. In dynamically-typed languages, the errors occur only once the program is executed, i.e. at runtime.

This means that a program written in a dynamically-typed language (e.g. JavaScript or Python) can compile even if they contain type errors that will prevent the script from running properly. On the other hand, if a program written in a statically-typed language (e.g. Scala or C++) contains type errors, it will fail to compile until the errors have been fixed.

## A new era of JavaScript

Because JavaScript is a dynamically-typed language, we can go about declaring variables, functions, objects and anything without declaring the type.

```javascript
var myString = "my string";

var myNumber = 777;

var myObject = {
  name: "Preethi",
  age: 26,
};

function add(x, y) {
  return x + y;
}
```

Convenient! But not always ideal, which is why tools like [Flow](https://flowtype.org) and [TypeScript](https://www.typescriptlang.org/) have recently stepped in to give JavaScript developers the *option* to use static types.

[**Flow**](https://flowtype.org/) is an open-source static type checking library developed and released by Facebook that allows you to incrementally add types to your JavaScript code.

[**TypeScript**](https://www.typescriptlang.org/), on the other hand, is a superset that compiles down to JavaScript, although it feels almost like a new statically-typed language in its own right. That said, it looks and feels very similar to JavaScript and isn't hard to pick up.

In either case, when you want to use types, you explicitly tell the tool about which file(s) to type-check. For TypeScript you do this by writing files with the `.ts` extension instead of `.js`, whereas for Flow you include a comment on top of the file with `@flow`

Once you've declared that you want to type-check a file, you get to use their respective syntax for defining types. One distinction to make between the two tools is that Flow is a type “checker” and not a compiler. TypeScript, on the other hand, is a compiler.

I truly believe that tools like Flow and TypeScript present a _generational shift and advancement_ for JavaScript. Personally, I've learned so much by using types in my day-to-day.

…Which is why I hope you'll join me on this short and sweet journey into static types.

The rest of this 4-part post will cover:

**I.** [**A quick intro to the Flow syntax and language**](https://dev.to/iampeekay/why-use-static-types-in-javascript-part-1)

**II.** [**Advantages of static types (with detailed walk-through examples)**](https://dev.to/iampeekay/why-use-static-types-in-javascript-part-2)

**III.** [**Disdvantages of static types (with detailed walk-through examples)**](https://dev.to/iampeekay/why-use-static-types-in-javascript-part-3)

**IV. So should we use static types in JavaScript or not?**

_(Note: I chose Flow over TypeScript in the examples in this post because of my familiarity with it. For your own purposes, please do research and pick the right tool for you. TypeScript is also fantastic.)_

Without further ado, let's begin!

## Part 1: A quick intro to Flow syntax and language

To understand the advantages and disadvantages of static types, we should first get a basic understanding of the syntax for static types using Flow. If you've never worked in a statically-typed language before, the syntax might take a little while to get used to.

Let's begin by exploring how to add types to JavaScript primitives, as well as constructs like Arrays, Object, Functions, and etc.

### __boolean__

Describes a `boolean` (i.e. true and false) value in JavaScript.

```javascript
var isFetching: boolean = false;
```

Notice that when we want to specify a type, the syntax we use is:

![](https://cdn-images-1.medium.com/max/800/1*Z79CcJO6h4DO_xKJMdK9zg.png)

### __number__

Describes an IEEE 754 floating point number. Unlike many other programming languages, JavaScript doesn't define different types of numbers (e.g. integers, short, long, floating-point etc). Instead, numbers are always stored as double precision floating point numbers. Hence, we only need one number type to define any number.

`number` includes `Infinity` and `NaN`.

```javascript
var luckyNumber: number = 10;

var notSoLuckyNumber: number = NaN;
```

### __string__

Describes a string.

```javascript
var myName: string = 'Preethi';
```

### __null__

Describes the `null` data type in JavaScript.

```javascript
var data: null = null;
```

### __void__

Describes the `undefined` data type in JavaScript.

```javascript
var data: void = undefined;
```

Note that `null` and `undefined` are treated differently. If we tried to do:

```javascript
var data: void = null;

/*------------------------FLOW ERROR------------------------*/
20: var data: void = null                     
                     ^ null. This type is incompatible with
20: var data: void = null
              ^ undefined
```

Flow would throw an error because the type `void` is supposed to be of type `undefined` which is not the same as the type `null`.

### __Array__

Describes a JavaScript array. We use the syntax `Array<T>` to describe an array whose elements are of some type `T`.

```javascript
var messages: Array<string> = ['hello', 'world', '!'];
```

Notice how we replaced `T` with `string`, which means we are declaring `messages` as an array of strings.

### __Object__

Describes a JavaScript object. There are a few different ways to add types to objects.

We could add types to describe the shape of an object:

```javascript
var aboutMe: { name: string, age: number } = {
  name: 'Preethi',
  age: 26,
};
```
We could define objects as maps where we map a string to some value:

```javascript
var namesAndCities: { [name: string]: string } = {
  Preethi: 'San Francisco',
  Vivian: 'Palo Alto',
};
```

We could also simply define an object as an `Object` type:

```javascript
var someObject: Object = {};

someObject.name = {};
someObject.name.first = 'Preethi';
someObject.age = 26;
```

However, this last approach lets us set any key and value on our object without restriction, which doesn't entirely add much value.

### __any__

Can represent any type, quite literally. The `any` type is effectively unchecked, so we should try to avoid using it unless absolutely necessary (e.g. when you need to opt out of type checking or need an escape hatch).

```javascript
var iCanBeAnything:any = 'LALA' + 2; // 'LALA2'
```
One situation you might find `any` useful for is when using an external library that extends another system's prototypes (e.g. Object.prototype).

For example, if you are using a library that extends Object.prototype with a `doSomething` property:

```javascript
Object.prototype.someProperty('something');
```

You may get an error:

```javascript
41:   Object.prototype.someProperty('something')
                       ^^^^^^ property `someProperty`. Property not found in
41:   Object.prototype.someProperty('something')
      ^^^^^^^^^^^^ Object
```

To circumvent this, we can use `any`:

```javascript
(Object.prototype: any).someProperty('something'); // No errors!
```

### __Functions__

The most common way to add types to functions is to add types to it's input arguments and (when relevant) the return value:

```javascript
var calculateArea = (radius: number): number => {
  return 3.14 * radius * radius
};
```

We can even add types to async functions (see below) and generators:

```javascript
async function amountExceedsPurchaseLimit(
  amount: number,
  getPurchaseLimit: () => Promise<number>
): Promise<boolean> {
  var limit = await getPurchaseLimit();

  return limit > amount;
}
```
Notice how our second parameter `getPurchaseLimit` is annotated as a function that returns a `Promise`. And `amountExceedsPurchaseLimit` is annotated as also returning a `Promise`.

### __Type alias__

Type aliasing is one of my favorite ways to use static types. They allow us to use existing types (number, string, etc.) to compose new types:

```javascript
type PaymentMethod = {
  id: number,
  name: string,
  limit: number,
};
```
Above, we created a new type called `PaymentMethod` which has properties that are comprised of `number` and `string` types.

Now if we want to use the `PaymentMethod` type, we can do:

```javascript
var myPaypal: PaymentMethod = {
  id: 123456,
  name: 'Preethi Paypal',
  limit: 10000,
};
```

We can also create type aliases for any primitive by wrapping the underlying type inside another type. For example, if we want to type alias a `Name` and `EmailAddress`:

```javascript
type Name = string;
type Email = string;

var myName: Name = 'Preethi';
var myEmail: Email = 'iam.preethi.k@gmail.com';
```

By doing this, we are indicating that `Name` and `Email` are distinct things, not just strings. Since a name and email aren't really interchangeable, doing this prevents us from accidentally mixing them up.

### __Generics__

Generics are a way to abstract over the types themselves. What does this mean?

Let's take a look:

```javascript
type GenericObject<T> = { key: T };

var numberT: GenericObject<number> = { key: 123 };
var stringT: GenericObject<string> = { key: "Preethi" };
var arrayT: GenericObject<Array<number>> = { key: [1, 2, 3] }
```

We created an abstraction for the type `T`. Now we can use whatever type we want to represent `T`. For `numberT`, `T` was of type `number`. Meanwhile, for `arrayT`, T was of type `Array<number>`.

Yes, I know. It's dizzying stuff if this is the first time you're looking at types. I promise the “gentle” intro is almost over!

### __Maybe__

Maybe type allows us to type annotate a potentially `null` or `undefined` value. They have the type `T|void|null` for some type `T`, meaning it is either type `T` or it is `undefined` or `null`. To define a `maybe` type, we put a question mark in front of the type definition:

```javascript
var message: ?string = null;
```
Here we're saying that message is either a `string`, or it's `null` or `undefined`.

We can also use maybe to indicate that an object property will be either of some type `T` or `undefined`:

```javascript
type Person = {
  firstName: string,
  middleInitial?: string,
  lastName: string,
};
```

By putting the `?` next to the property name for `middleInitial`, we indicate that this field is optional.

### __Disjoint unions__

This is another powerful way to model data. Disjoint unions are useful when we have a program that needs to deal with different kinds of data all at once. In other words, the shape of the data can be different based on the situation.

Extending on the `PaymentMethod` type from our earlier generics example, let's say that we have an app where users can have one of three types of payment methods. In this case, we can do something like:

```javascript

type Paypal = { id: number, type: 'Paypal' };
type CreditCard = { id: number, type: 'CreditCard' };
type Bank = { id: number, type: 'Bank' };
```

Then we can define our PaymentMethod type as a disjoint union with three cases.

```javascript
type PaymentMethod = Paypal | CreditCard | Bank;
```
Payment method now can only ever be one of these three shapes. The property `type` is the property that makes the union type “disjoint”.

We'll see more practical examples of disjoint union types later in part 2.

Alright, almost done. There are a couple other features of Flow worth mentioning before concluding this intro:

**1) Type inference**: Flow uses type inference where possible. Type inference kicks in when the type checker can automatically deduce the data type of an expression. This helps avoid excessive annotation.

For example, we can write:

```javascript
/* @flow */

class Rectangle {
  width: number;
  height: number;

  constructor(width, height) {
    this.width = width;
    this.height = height;
  }

  circumference() {
    return (this.width * 2) + (this.height * 2)
  }

  area() {
    return this.width * this.height;
  }
}
```

Even though this Class doesn't have types, Flow can adequately type check it:

```javascript
var rectangle = new Rectangle(10, 4);

var area: string = rectangle.area();

// Flow errors
100: var area: string = rectangle.area();
                        ^^^^^^^^^^^^^^^^ number. This type is incompatible with
100: var area: string = rectangle.area();
               ^^^^^^ string
```

We tried to define `area` as a `string`, but in the `Rectangle` class definition we defined `width` and `height` as numbers, so based on the function definition for `area`, it must be return a `number`. Even though we didn't explicitly define types for the `area` function, Flow caught the error.

One thing to note is that the Flow maintainers recommend that if we were exporting this class definition, we'd want to add explicit type definitions to make it easier to find the cause of errors when the class is not used in a local context.

**2) Dynamic type tests**: What this basically means is that Flow has logic to determine what the the type of a value will be at runtime and so is able to use that knowledge when performing static analysis. They become useful in situations like when Flow throws an error but you need to convince flow that what you're doing is right. I won't go into too much detail because it's more of an advanced feature that I hope to write about separately, but if you want to learn more, it's worth reading through the [docs](https://flowtype.org/docs/dynamic-type-tests.html).

## We're done with syntax

We covered a lot of ground in one section! I hope this high-level overview has been helpful and manageable. If you're curious to go deeper, I encourage you to dive into the [well-written docs](https://flowtype.org/docs/) and explore.

With syntax out of the way, let's finally get to the fun part: exploring the advantages of using types!