Do TypeScript allows us to program like Java?

I think in many ways TypeScript is superior to Java but unfortunately, TypeScript is not a magical tool that fixes all the things wrong with JavaScript and in fact, is very dynamic and much closer to JavaScript than to Java. From my experience, many developers (especially Angular developers) don’t get that. TypeScript is basically JavaScript with some type annotations that are removed during compilation.. so basically it’s just JavaScript with all the 💩 it comes. In this article I will mention some of the things that you need to be aware of as a Java developer.

Optional return statement

In TypeScript it is perfectly OK to miss some of the return statements and this may cause horrible bugs. The code below will display ‘undefined’ instead of compilation error. Imagine a larger function in production with some if statements and a missing return 🤬.

function abs(a: number): number {
  if (a < 0) {
    return -a;
  }
}
alert(abs(1));

Functions are also values

A programming language is said to have First-class functions when functions in that language are treated like any other variable. For example, in such a language, a function can be passed as an argument to other functions, can be returned by another function and can be assigned as a value to a variable. In TypeScript functions are first class citizens. This is really cool, but also has some consequences  and in case you are not aware of this fact, it can be dangerous. Let’s take the following example:

class Student {
  gradeMath = 1
  gradePhysics = 1

  checkStudentStatus() {
    if (this.isPassed) {
      alert('Passed');
    } else {
      alert('Failed!');
    }
  }
  isPassed(): boolean {
    return this.gradeMath > 5 && this.gradePhysics > 5;
  }
}

// This will always display 'Passed' even though both grades are 1.
// In the if statement we don't use the function call isPassed()
// but the function value isPassed.
new Student().checkStudentStatus()

Because TypeScript evaluates any object that is not undefined to true and because every function in JavaScript is also an object the condition above can be translated to this.isPassed !== undefined.

The this that is not this

In TypeScript the this keyword behaves like in JavaScript and it’s different from Java. In my opinion in some way it is more intuitive than in other languages but still it is different from Java and may cause a lot of headaches if you are not aware of this fact. The main difference is that the this keyword behavior is dynamic and it’s determined by how a function is called. I won’t enter in more details, because for that I’ll need a separate blog post, but you can read about it here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this.

Meanwhile you can also take a look at these example:

class SetIntervalTest {
  private someNumber: number = 1; 

  trigger() {
    setTimeout(this.setIntervalCallback, 400);
  } 

  private setIntervalCallback() {
    // setTimout is executed from the Browser Window context
    // so when this function is executed `this` will be the Windows
    // and not the SetIntervalTest instance.
    alert(this.someNumber);
  }
} 

// Prints undefined because this.someNumber is actually
// Windows.someNumber and it's not defined.
new SetIntervalTest().trigger();

Another example:

class Game {
  name = 'TestGame';
  clearBoard() {
    alert(name + ' cleared');
  }

  scheduleClearBoard() {
    setTimeout(function () {
      // What is "this" in this context?
      // And NO, it is not an instance of the Game class,
      // this code will crash!
      this.clearBoard();
    }, 1000);
  }
}

In TypeScript you can simulate the this behavior from Java using arrow functions. If you declare the method like below it will work, this will be the current instance of the Game class.

scheduleClearBoard() {
  setTimeout(() => {
    this.clearBoard();
  }, 1000);
}

Optional Semicolon is a mess

Another weird thing inherited from JavaScript is the optional semicolon. In order to obtain this behavior the interpreter will automatically insert a semicolon on newline. A consequence of this implementation is that if you hit enter after the return statement such as in the example below… the code will always return undefined:

class Student {
  isPassed(): boolean {
    return
      this.gradeMath > 5 &&
      this.gradePhysics > 5;
  }
}
// This will always return undefined!!!
new Student().isPassed();

The code above is basically the same as:

class Student {
  isPassed(): boolean {
    return undefined;
    this.gradeMath > 5 &&
    this.gradePhysics > 5;
  }
}

This is such a nasty source a bugs that most linters will complain about it and they’ll display a warning related to unreachable code… so this can be easily avoided if you use an IDE such as Visual Studio Code.

No type safety at runtime

One thing that many beginners do not understand about TypeScript is that it does not guarantee type-correctness at runtime. Your TypeScript code might be fully typed and the compiler ensures you that everything must be correct… but at runtime you still get errors because your variables might be of the wrong types! Type error might enter your system at the “untyped” boundaries such as: when getting JSON from the network, from local storage or even from the DOM, when using the any keyword, when using any JavaScript library… By design TypeScript does no type checks at runtime:

export class Student {
  name: string;
  printName() {
    alert(this.name);
  }
}

// You can assume that this is an HTTP call.
function loadStudent(): Promise {
  return Promise.resolve({
    name: "John Doe"
  });
}

loadStudent().then(student => {
  student.printName();
});

In the code above the compiler will tell us that everything is OK but at runtime the code will crash because the result object is a JSON object not an instance of the Studentclass so it has no printName method.

The equality operator

In Java, as in many other languages, we have the == and !=equality operators.  In order to be confusing, TypeScript has two sets of equality operators: === and !==, and their evil twins == and !=. The first ones work as expected, the second ones operate by some rules that are complicated and unmemorable. For example:

'' == '0' // false
0 == '' // true
0 == '0' // true

false == 'false' // false
false == '0' // true

false == undefined // false
false == null // false
null == undefined // true

' \t\r\n ' == 0 // true

 

The null and undefined nightmare

In Java one of the most common source of bugs is related to null values and the infamous NullPointerException. To fix this, many libraries introduced optional types and you can also use the Null Object Pattern to avoid these kind of exceptions. In TypeScript you have not one but two null types: null and undefined! This undefined thing is not null but is not a value either.  It is basically a horseshit, a joke of the creators of JavaScript on us.. poor bastards.  So good luck checking for both null and undefined!🤦🤦🤦

No Integer Type

Do you remember the pillar of any programming language, the native type of the CPU, the absolutely required type for any kind of algorithm that requires byte level operations? Do you heard about the almighty integer type? Forget it! We don’t need it in JavaScript because we have monads, currying and Eric Elliotts. We are JavaScript coders who love functional shit but hate with passion anything remotely related to real programming. JavaScript has only one numerical type and that’s (double precision aka no precision) floating point. This is the only language I’ve ever used that doesn’t have an integer type (and I’ve used many).

Weird Arrays

There are no Java style arrays in TypeScript: arrays and maps are the same thing. Because arrays behaves as maps and both of them are totally dynamic we have no array bounds exceptions and the array will automatically expand to the required number of elements but will not shrink when we delete an element. This may help you program if you are a beginner but it’s weird and may lead to serious issues:

let arr = [];
// prints 0
console.log(arr.length);
// prints "undefined" but: No array bounds exception?
console.log(arr[3]); 

// will automatically allocate an array of 4 elements.
arr[3] = "hi";
// prints 4 but we added only one element.
console.log(arr.length);
// apparently we can use the string "3" as index??
console.log(arr["3"]);
// Delete element... array remains the same.
delete(arr[3]);
// prints 4??? There are no elements in the array!
console.log(arr.length);
// we can use splice, super intuitive function name!
arr.splice(3);
// now the element is removed and length is 3.
console.log(arr.length);

Conclusion

If you are a Java developer and you are still thinking that TypeScript is almost the same as Java… as Tyrion Lannister would say: You’re fucked!

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