A love letter to TypeScript
Tags: typescript, javascript
Published: 2019-08-07 02:08:43

---
title: A love letter to TypeScript
published: true
description: Writing to TypeScript about its wonderful qualities and why I feel in love to it.
tags: typescript, javascript
cover_image: https://thepracticaldev.s3.amazonaws.com/i/5obtt11szn1xw4zdhwn8.png
---

Dear TypeScript, I know that your brother JavaScript sometimes may not want to see us together, but I think your qualities are worth it, that's why I love you! 

Jokes apart, this is really a post that I have been desiring to write for a long time since I started to actually study the many features that TypeScript have and how wonderful it is. The code in the cover image is not just for show, in a simple example like that I can show many reasons why I'm in love with TypeScript and I want to use it as much as possible from now on. Therefore, without further ado, let's go write this love letter bit by bit. 
 
When we talk about JavaScript we always think about flexibility. It confers a lot of flexibility in the way you write code, JavaScript is very permissive, you can add fields in objects, remove fields, functions can be passed as parameters, arrays can hold elements of any "type" (JavaScript has a very loose concept of type). However, all this flexibility has a cost. When I see a application with more than 100 lines and 1 file written in JavaScript it always looks a mess to me, no offense. I don't know from where things comes from and where they go. It is like stepping into a minefield. My background is from Java, where you have control of almost everything you code, way too much control sometimes. 

That's where TypeScript comes to play, it mixes the flexibility of JavaScript, but putting it at bay with the control that static typed languages offer. For me, it have the best of two worlds: JavaScript and Java (never confuse them). So, let's go to the example. First, the `Letter` interface. 

```typescript
export interface Letter {
  from: string;
  to: string;
  message: string;
}
```
Okay, pretty normal, right? One thing that I like in interfaces in TypeScript is that you can have both properties and methods defined and the class that will implement them will need to have all these properties to satisfy it. It is different in Java, where "properties" are in the end constants inside an interface, they are not properties. Interfaces in TypeScript, however, show their power along with other classes. So, we present below the `LoveLetter` class.
```typescript
export class LoveLetter {
  constructor(public from: string, public to: string) {}

  get message(): string {
    return `I love you, ${this.to}`;
  }
}
```
Just by looking at the class you may not realize it if you don't know TypeScript wonderfulness, but this class completely satisfies the `Letter` interface, 100%! First, the constructor. In Java it is always annoying to have to add parameters and assign them to the class properties right after, it is unnecessary boilerplate! I love TypeScript approach where by inserting `public`, `private`, etc. to the constructor's parameters you are declaring a class property and assigning the parameters' value to it all in one go. Therefore, `LoveLetter` class has the string properties `to` and `from` that `Letter` requires.

"But how about `message`? In `LoveLetter` it is a method, not a string property!", you might say. That's another very interesting feature of TypeScript: "getter methods". It can be used much like getters in Java, for example, but I think in TypeScript it has a gotcha that Java doesn't have. When you add the `get` word before the function, TypeScript will  treat it as if it were a property! So, we can do this: `letter.message` instead of this: `letter.message()`. Since it is considered a property to TypeScript it is a okay to satisfy the `Letter` interface. It is very useful when you want to shape the data in another way, for example, for visual purposes, like I did with "I love you, #name#", using string interpolation to insert the name of recipient. It may not look a big difference in a simple example, but when you are trying to satisfy some big interfaces or having more complex use cases, it comes in handy. 

For some who may be used to Java it may sound strange that the class implements the interface like that without any formal declaration like `class Foo implements Bar` in Java, but it is one of the reasons why interfaces are so powerful in TypeScript, the class satisfies the interface merely by its shape, a formal declaration is not necessary. You can declare formally, however:
```typescript
export class LoveLetter implements Letter {
  constructor(public from: string, public to: string) {}

  get message(): string {
    return `I love you, ${this.to}`;
  }
}
```
The declaration is exactly like Java and that way you will have error messages at the class level if the class is not satisfying the interface, but generally you will not have to be that explicit. So, if one class satisfies an interface only by shape, then you can go to the last part of our example:
```typescript
const sendLetter = (letter: Letter) => {
  console.log(
    `From: ${letter.from}
    To: ${letter.to}
    
    ${letter.message}
    `
  );
};

const loveLetter = new LoveLetter('Developer', 'TypeScript');
sendLetter(loveLetter);
```
Here we have a function that is assigned to a constant and is declared as an arrow function. In this case it doesn't have any special meaning, but arrow functions can make the code more elegant, principally when TypeScript/JavaScript are the home of callbacks. Also, it can solve some concerns around scopes, principally when it comes to `this`, but we can talk about that in the future. Then we create a new `LoveLetter` and assign it to a constant, nothing special, but the next line show some of the power of interfaces. Although the function receives a `Letter` as parameter, since `LoveLetter` satisfies the interface 100% then you are good to call the function with an instance of `LoveLetter` as well! And what it is better is that you don't need to tell TypeScript anywhere that, it  knows it automatically. Again, the interface is evaluated by its shape, if the shape is right, you are good to go! 

It has been very interesting to learn more about TypeScript everyday and how it fuses the things that I like the most in the languages I already know in one beautiful language. There are many other features that are worth mentioning, but I think with this simple example you can get a sense of TypeScript greatness. I believe that TypeScript has a bright future in the market and I recommend it to everybody. Don't worry, I will not get jealous by the popularity of my dear TypeScript.