Skip to content

Latest commit

 

History

History
74 lines (61 loc) · 2.86 KB

TypeScriptIsActuallyJavaScriptAndOneStillHasToBeCareful.md

File metadata and controls

74 lines (61 loc) · 2.86 KB

TypeScript is actually JavaScript and one still has to be careful

TypeScript, although very promising language, does not solve fundamental JavaScript's issue (feature?) with "this" property binding. TypeScript can lead to unfortunate errors since it is heavily used by people coming from C#/Java communities, who bring coding patterns with them. Let's have a look at code example from TypeScript playground:

class Greeter {
    greeting: string;
    constructor(message: string) {
        this.greeting = message;
    }
    greet() {
        return "Hello, " + this.greeting;
    }
}
let greeter = new Greeter("Alexander");
console.log(greeter.greet());  // Hello, Alexander

Now, lets make slight change to the last two code lines:

let greeter = new Greeter("Alexander").greet;
console.log(greeter());  // Hello, undefined

This happens because greet() method references this and when you make a call of greet() not on the object, this gets bound to the global scope. It's really unfortunate that one can so easily destroy TypeScript object's integrity. In C# this example would work just fine and therefore C# developers should be extra careful to avoid this pitfall:

using System;                    
public class Program
{
    class Greeter {
        string greeting;
        public Greeter(string message){
            this.greeting = message;
        }
        public string greet(){
            return "Hello, " + this.greeting;
        }
    }
    public static void Main()
    {
        Func<string> greeter = new Greeter("Alexander").greet;
        Console.WriteLine(greeter());  // Hello, Alexander
    }
}

Now, even knowing all rules of this binding (take a look at this article if you are not aware of these rules), I was caught when I was coding in TypeScript class for Angular 2 framework:

export class Timer {
    @Output() onFinished = new EventEmitter();
    @Input() duration;

    start() {
        updateClock();
        var timeinterval = setInterval(updateClock, 1000);

        function updateClock() {
            this.duration = this.duration - 1;
            if (this.duration <= 0) {
                clearInterval(timeinterval);
                this.onFinished.emit({});
            }
        }
    }
}

See how updateClock local function starts accessing Timer properties via this? Seriously, I was debugging this code full of surprise trying to understand why am I getting an error. And the reason was that updateClock() is invoked without binding to any object which meant binding to the global scope again.

Conclusion: TypeScript is great, but guys, don't relax, remember you are still coding in JavaScript, not C# or Java. And probably avoid using classes and this altogether.