DEV Community

Cover image for Might I introduce you to my friend TypeScript?
Gaurang
Gaurang

Posted on • Updated on

Might I introduce you to my friend TypeScript?

Table of Contents

The lead-up

A few days back, I wrote an 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.

Great read. Love the analogies. But I'm a javascript developer and there is no support for interfaces in javascript currently. How would I create a contract for other developers to follow?

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.

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?

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");

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.

Simple Explanation

What is duck typing?

“If it walks like a duck and quacks like a.... etc” - YES, but what does that mean??!

We're interested in what "objects" can do, rather than what they are.

Let's unpack it with an example:

Explanation of Duck Typing

See below for further detail:

Examples


Consider you are designing a simple function which gets an object of type Bird and calls its walk() method. There are two approaches you can think of:

  1. This is my function, and I must be sure that it only accepts the Bird type or the code will not compile. If…

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.

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.

// 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
Enter fullscreen mode Exit fullscreen mode

Now that we've introduced types to JavaScript, it makes lot more sense to have interfaces. Undoubtedly, TypeScript has them.

// 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'
}
Enter fullscreen mode Exit fullscreen mode

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 and see it live how TypeScript gets converted to JavaScript. Check out their examples. It's fun! :D

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 and strict/loose comparison or type-coercion.

Consider this tweet:


Confused?
Here, + "a" turns into NaN (Not a Number. Yes, that's a thing in JavaScript) because + acts as the unary plus operator 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".
console.log(("b" + "a" + + "a" + "a").toLowerCase()); console.log(+"a"); console.log("ba" + NaN + "a"); console.log("baNaNa".toLowerCase());

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]

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.
Screenshot - parameter info pop-up
Screenshot - TypeScript file that helps provide IntelliSense

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.
It'll definitely increase your productivity and your team's.

Oldest comments (3)

Collapse
 
chari16 profile image
Bhavesh Sadanand Chari

You made up a valid point there, using typescript would definitely lead to less syntactically error but logically error still can be produced.
Typescript will give you a upper hand for better debugging. Also the team on a larger project will be much happier as they will be less prone to make errors.

Collapse
 
gaurang847 profile image
Gaurang

Yeah man. Reminds me of Einstein's famous quote.

"Two things are infinite: the universe and human stupidity; and I'm not sure about the universe."
— Albert Einstein

We can only try to do our best! I too feel that TypeScript helps you in writing better code.
I'd argue though that if your code expects an integer and what it gets is a string. (Or worse, an object!) Then that's in fact a logical error.

Collapse
 
roh_dee profile image
Rohan

Quite insightful and informative.