Might I introduce you to my friend TypeScript?
Tags: javascript, codenewbie, typescript
Published: 2020-05-03 11:04:24

# Table of Contents
* [The lead-up](#lead-up)
* [Why interfaces in JavaScript make no sense](#interface-non-sense)
* [Might I introduce you to my friend Typescript?](#typescript)
* [Do I really need it though?](#do-i-need-typescript)
* [Conclusion](#conclusion)

<a name="lead-up" \>
# The lead-up
A few days back, I wrote an [article][interface_article] explaining the concept of interfaces in Java (or object-oriented programming in general). In the process, I also debunked a popular myth that I found to exist among Java novices.
I was glad to find that it was so well received. (Thanks all of you awesome people! You rock!! :D )
I want to address this particular comment though.
{% devcomment mpai %}

My answer to this (the short one) is "You can't. Nope. No. Nada. Zilch. Naught". You don't have interfaces in JavaScript.
And I don't believe there exists any other way to enforce method contracts in JavaScript the way you do in Java with the help of interfaces.

<a name="interface-non-sense" \>
# Why interfaces in JavaScript make no sense
With the help of interfaces, you define three things in Java:
1. What methods should compulsory exist
2. The input of these methods - how many parameters they will take and what shall be the data-type of each
3. The output of these methods - what shall be the data-type of the returned value

When you're talking about having interfaces in JavaScript, you're probably only thinking about point 1. But, what about points 2 and 3?
{% runkit %}
function dummyMethod(definedParam1, definedParam2){
    // `arguments` is a special object that exists inside every JavaScript function.
    // It contains all the input-parameters passed to the function.
    console.log(arguments)
}

dummyMethod("a", "b");
dummyMethod();
dummyMethod("a", "b", "c", "d", "e");
{% endrunkit %}
You can see that the function `dummyMethod` is defined to take exactly 2 parameters as input.
But, regardless of whether I pass less parameters or more, the function takes them without complaining.

Not only does JavaScript lack the kind of type-checking that happens in Java. But also, there's no policing on the number of arguments of a function.
Furthermore, JavaScript has no notion of 'return type of a function'.

For a language like Java which is statically typed, it makes sense to have interfaces. There, things break if methods are called with the wrong parameters.
But JavaScript follows duck-typing; which is considered to be the antithesis to interfaces.

{% stackoverflow 40434829 %}
{% stackoverflow 33631704 %}

<a name="typescript" \>
# Might I introduce you to my friend Typescript?
TypeScript is really just JavaScript + types. Or as they call it, the typed _super-set_ of JavaScript.
So, remember how you write `int total`, `boolean isEmpty`, `String name` in Java/C++. Yeah, Typescript is basically JavaScript with all that.

{% link educative/typescript-tutorial-a-step-by-step-guide-to-learn-typescript-4g4p %}

TypeScript doesn't let you pass more parameters to a function, or less, than what has been defined.
It also doesn't let you pass parameters of the wrong type.

```typescript
// Source: https://www.typescriptlang.org/docs/handbook/functions.html
function buildName(firstName: string, lastName: string) {
    return firstName + " " + lastName;
}

let result1 = buildName("Bob");                  // error, too few parameters
let result2 = buildName("Bob", "Adams", "Sr.");  // error, too many parameters
let result3 = buildName("Bob", "Adams");         // ah, just right
```

Now that we've introduced types to JavaScript, it makes lot more sense to have interfaces. Undoubtedly, TypeScript has them.
```typescript
// Source: https://devblogs.microsoft.com/typescript/walkthrough-interfaces/
interface Greetable {
    greet(message: string): void;
}

function helloEnglish(g: Greetable) {
    g.greet('Hello there!'); // OK
    g.greet(42); // Not OK -- 42 is not a string
    g.greep('Hi'); // Not OK -- 'greep' is not a member of 'Greetable'
}
```

Note that the type system of TypeScript is like an add-on over JavaScript. It is not a separate language.
A script written in TypeScript is not runnable on its own.
When you run the compiler over your `.ts` file, it gets converted to a normal JavaScript file without types.
You can even check out their [playground][ts_playground] and see it live how TypeScript gets converted to JavaScript. Check out their examples. It's fun! :D

<a name="do-i-need-typescript" \>
# Do I really need this though?
If you're an indie developer, who has spent considerable time working with vanilla JS, you might've grown fond of the type-less flexibility, and smartness of the language to dynamically infer the type of variables. Without bothering you, so that you can focus on writing your logic.

You might be wondering whether this overhead of declaring types is really worth it or is just an unnecessarily glorified self-infliction.
Maybe it's part of some grand propaganda conjured by Microsoft, spread by Java/C++ cult-followers, and backed by those pretentious developers who grill you for not following a certain coding standard, or ask a random language-quirk related question in interview and judge the candidate critically for not knowing the answer.

Well... Your suspicions might as well be true. I have no proofs to tell you otherwise. ¯\\\_(ツ)_/¯
But, here's the thing. Just by looking at the name, you can't tell if `total` is a Number or String. You'll have to trace it back to where it's defined to know that. If it's a value being passed from another function, you'll need to trace it back there as well.
The flexibility of JavaScript might feel like a boon when you're writing your software ground-up. But it feels like a curse when you're receiving a knowledge-transfer (KT) session from another developer.
Larger the codebase and larger the number of people that have worked on it, the more difficult it is to understand it.

Also, while writing your own feature, you'd obviously want your code to be resilient to the mistakes of previous code. So, you can't trust it. And you'll need to deliberately cast it `total = Number(total)`.
If you get a `Nan`, you can handle it accordingly.
Imagine if yours is an e-commerce website with the user-base of lakhs. You miss this said case and your code goes to production just before a major sale. A user clicks on checkout and boom! Server crashed!

Forgive me if the scenario sounds a little presumptuous. But, at the very least, you must agree that it is plausible.
Just Google "common JavaScript mistakes". Most results will list at least one mistake that is related to types.
Specifically, the ones related to [+ operator][plus-operator-mistake] and [strict/loose comparison][comparison-mistake] or type-coercion.

Consider this tweet:
{% tweet 1161012147884707840 %}
Confused?
Here, `+ "a"` turns into `NaN` (Not a Number. Yes, that's [a thing in JavaScript][nan]) because + acts as the [unary plus operator][unary_plus] that tries to cast any value to a number. And "a" is literally not a number.
Thus, `"b" + "a" + + "a" + "a"` becomes `"ba" + NaN + "a"`.
Now, the NaN gets cast to a string and `"ba" + NaN + "a"` transforms to `"baNaNa"`.
Convert it to lowercase and that's how you get `"banana"`.

{% runkit %}
console.log(("b" + "a" + + "a" + "a").toLowerCase());
console.log(+"a");
console.log("ba" + NaN + "a");
console.log("baNaNa".toLowerCase());
{% endrunkit %}

With a type system in place, you just immediately know whether a variable is a string or a number or something else altogether. (Who knows.. It could be an object, for heaven's sake!)
And say, if you're assigning a string to a number variable, the error will be caught immediately at compile time.

> _"I completely understand that if you're a single person writing a large JavaScript application where you know exactly what every object is. And  you've made it all. And it's beautiful. And it's fast. And you can change it into any other thing that you want, because you know everything about it in your head, right?_
>
> _But once you start programming larger apps in teams. Y'know, we just find that teams want to have the ability to agree upon [that] in between these two modules, we have to follow a contract. And they want to have things that can validate that they're adhering to the contract. Y'know, you can't just like run into each others offices and like compare code all the time._
>
> _You want to have some sort of agreed upon way that you write this down. And you also want, when new people come in, something that tells you a bit about what this 100-1000 line codebase does. How am I supposed to understand what this paramteter `x` is. I don't know. I don't know `x`. Tell me! With an annotation, right?"_
>
> — [Anders Hejlsberg, What is TypeScript and why with Anders Hejlsberg [13:30]](https://www.hanselminutes.com/340/what-is-typescript-and-why-with-anders-hejlsberg)

Here's another cool thing.
If you use Microsoft VS Code, and you've been using its IntelliSense features (code-completion, parameter info, member list, etc.), they are [powered by TypeScript][vscode_typescript].
![Screenshot - parameter info pop-up](https://dev-to-uploads.s3.amazonaws.com/i/kj1oq5qya9lhn59ipfse.png)
![Screenshot - TypeScript file that helps provide IntelliSense](https://dev-to-uploads.s3.amazonaws.com/i/zgnzlkc9r8hlgwlzzfv4.png)

<a name="conclusion" \>
# Conclusion
Even with the absence of types and interfaces, I've seen great software written by people in vanilla JavaScript; mostly at startups with small teams though.
So, if vanilla-JS is your thing, there's nothing wrong in using it.

But, if you're working on larger projects, or/and you're bothered by the lack of interfaces in JavaScript (and by extension, lack of types), you should consider using [TypeScript][typescript].
It'll definitely increase your productivity and your team's.




[typescript]: https://www.typescriptlang.org
[interface_article]: https://dev.to/gaurang847/do-you-really-understand-interfaces-1g7l
[plus-operator-mistake]: http://www.javascriptgotchas.com/gotchas/values-plus.html
[comparison-mistake]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators
[ts_playground]: https://www.typescriptlang.org/play/index.html
[vscode_typescript]: https://code.visualstudio.com/docs/nodejs/working-with-javascript
[nan]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NaN
[unary_plus]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Unary_plus