Wednesday, September 23, 2015

TypeScript vs. JavaScript

Seems like a lot of people want to know what they should use for web development: TypeScript or JavaScript? Well, like anything else it depends on the context. They are two different tools used for two different purposes.

JavaScript is very loose; there is no compiling or type checking. You can quickly make a small app or write some form validation code. There's a lot less typing involved and you don't have to think too much about structure. In these situations using JavaScript is more productive.

TypeScript on the other hand is better suited to large single page application with complex interactions spanning multiple source files. As the number of lines of code increases applications tend to get more complex. This is where TypeScript, with it's type checking and added structure, help you manage the complexity and become more productive.

The graph below illustrates what I'm talking about. Up to a certain point JavaScript is more productive because there's less overhead. But after you pass that point TypeScript becomes more productive because it's easier to manage the complexity.


I can't tell you what the specific lines of code are. For me it's about a page or two of code. My general rule is if you can hold the entire app in your head then use JavaScript, otherwise use TypeScript.

How does TypeScript reduce complexity? As its name implies, types. By giving your variables and parameters types it makes it easier for the compiler to make sure you didn't accidentally use a wrong type, and easier for you to know what the variable represents. It's hard enough even with types to determine what a variable is used for, so why make it harder?

TypeScript also supports classical OOP in the form of classes and interfaces. These are basically your custom types. Classes and interfaces give a more rigid structure to your code. Contrast that to plain old JavaScript objects which have no structure at all. They can be whatever anyone wants them to be and there's no way for you to know with inspecting the contents of the object.

TypeScript provides better tooling for your IDE. In JavaScript it's very hard for your IDE to determine what type a variable or parameter is because, well, it's untyped. With TypeScript the IDE knows exactly what type something is and can tell you. For example, intellisense can tell you exactly what types the parameters of a function expect taking the guesswork out of calling it. It's like built in documentation.

When you compile TypeScript it's like running unit tests on your code. For example, say you changed the signature of a function and forgot to change all the references to it. You immediately know there is a problem and where it is. In my experience this is much faster than running your app, getting an error, looking at the stack trace (if there is one), then finding the errant code.

All of this makes for less things you have to keep in your head. Remember, code isn't written for computers to understand, it's written for humans to understand (otherwise we'd all be writing code in 0's and 1's). 

Even though TypeScript is an extension of and compiles to JavaScript they are two very different tools. Knowing what context to use each in can help you write and maintain your code more efficiently.

Thursday, September 17, 2015

Typescript Function Overloading

Function overloading in TypeScript is a little enigmatic and complicated to learn at first. It doesn't work like traditional overloading in other languages like C# or Java where you just create a new function with the same name but different parameters. Function overloading in TypeScript is more like defining facades for a function.

The reason TypeScript doesn't have traditional function overloading is because JavaScript doesn't support overloading. The reason JS doesn't support overloading is because JS doesn't care about function signatures. You can pass any parameters you want to a function in JS. Therefore you can't define two functions with the same name because it has no way to tell them apart.

As I said, function overloading in TypeScript is more like defining facades or interfaces to a function than overloading. The way it works is you define a function that can handle all of the different parameters that you want to throw at it, just as you would in JavaScript, then define your facades to make it easier to call that function.

An example would make it easier to see how this works. Say we want to have a getter and setter methods with the same name. First let's just write it as one function without any overloads.

class Foo{
    private _bar: string;
    public bar(val?: string): any {
        if (val || val === ""){
            this._bar = val;
        }
        else return this._bar;
    }
}

If a string parameter is passed in it will set the backing variable and return nothing. If no parameter is passed it will return the value of the backing variable. This will work, but the function signature isn't very intuitive or user friendly. So let's add some overloads, or facades, that will make it more apparent how to use it.

class Foo{
    private _bar: string;
    public bar(): string;
    public bar(val: string): void;
    public bar(val?: string): any {
        if (val || val === ""){
            this._bar = val;
        }
        else return this._bar;
    }
}

We've added two signature overloads. Notice that the overload signatures must come before the actual function body. The first is our getter which takes no parameters and returns a string. The second is our setter which takes a string parameter and has a return type of void. Both of these signatures must be compatible with the real function definition's signature.

Let's look at another example. This time we'll make a class called Color and overload the constructor so that you can either pass in a string color identifier or red, green and blue components.

class Color{
    public stringValue: string;
    constructor(def: string);
    constructor(r: number, g: number, b: number);
    constructor(rOrDef: any, g?: number, b?: number){
        if (typeof(rOrDef) === "string"){
            this.stringValue = rOrDef;
        }
        else{
            this.stringValue = "rgb("+rOrDef+","+g+","+b+")";
        }
    }
}

Notice that the first parameter rOrDef is defined as "any" so that it can take a string or number. The g and b parameters are marked as optional. Then we can simply create our two signature facades, one that takes one string parameter, and another that takes three number parameters.

Once you realize that there is no such thing as function overloading in TypeScript that's the key to understanding it. You're actually creating facades that make it easier for someone to call a function that will accept many different types of parameters.

TypeScript Private Constants and Minification

I'm currently working on a TypeScript app that has a lot of private static values inside the classes. They don't need to be visible to the outside world, but making a variable "private static" doesn't mean that it will really hide the variable in the compiled JavaScript. It's merely a hint to the compiler to limit access to the insides of the class. Here's an example:

module TestMod {
    export class TestClass {
        private static privateStatic = "I'm private and static";
    }
}

Compiles to:

var TestMod;
(function (TestMod) {
    var TestClass = (function () {
        function TestClass() {
        }
        TestClass.privateStatic = "I'm private and static";
        return TestClass;
    })();
    TestMod.TestClass = TestClass;
})(TestMod || (TestMod = {}));

As you can see privateStatic is completely accessible outside the object after compilation. If you're writing a library that may be used by JavaScript this isn't good (but I probably wouldn't write a JavaScript library in TypeScript). For me the biggest implication of this is that when you minify your JavaScript those members' names can't be modified. The minifier doesn't know that private static variables will never be accessed from the outside.

After running it through a minifier you get this:


var TestMod;!function(t){var a=function(){function t(){}return t.privateStatic="I'm private and static",t}();t.TestClass=a}(TestMod||(TestMod={}));

As you can see privateStatic was not renamed to a shorter name as you might have wanted.

One way we can remedy this is to move the private static variables up into the module. As long as you don't mark them with the export keyword they will be completely hidden from the outside world.


module TestMod {
    var _privateStatic = "I'm private and static";
    export class TestClass {
        public foo() { return _privateStatic; }
    }
}

Compiles to:
var TestMod;
(function (TestMod) {
    var _privateStatic = "I'm private and static";
    var TestClass = (function () {
        function TestClass() {
        }
        TestClass.prototype.foo = function () { return _privateStatic; };
        return TestClass;
    })();
    TestMod.TestClass = TestClass;
})(TestMod || (TestMod = {}));

Now _privateStatic is assigned to a variable in a closure. If we look at the minified JavaScript you can see that _privateStatic has been changed to "n" giving you better minification.

var TestMod;!function(t){var n="I'm private and static",o=function(){function t(){}return t.prototype.foo=function(){return n},t}();t.TestClass=o}(TestMod||(TestMod={}));

One problem with this technique is readability. Notice that I change the name from privateStatic to _privateStatic. I prefix the variable names with an underscore to make it clear that they are defined outside the class but are still private.

If you have a lot of static variables or constants in a class and you're looking to save some bytes in your minified application you might take a look at using this technique. It may make your code a little harder to read but the trade off is you get a smaller app. 

TypeScript Lambda Gotcha

I came across a little gotcha today in TypeScript that I hadn't thought about before (but should have known better). When you use lambdas syntax, if you don't wrap it in curly braces it returns the result of the expression. In most cases this is probably fine, but not if the caller of your function is looking for a return type. I was using the LoDash _.each() function which allows you to pass back false if you want to break the loop. And unfortunately I was setting a boolean variable in the lambda without using curly braces. So every time I set the variable to false it broke the loop and I got bugs :-(.

For example, here I'm not using braces around my lambda expression, so whenever item.condition is not 1 it breaks the loop.

_.each(items, (item) => item.visible = (item.condition === 1));

This compiles down to:

_.each(items, function(item) { return item.visible = (item.condition === 1); });
See how it inserted a return statement? That's not we wanted!

By simply adding curly braces the return is removed and you get the correct behavior.

_.each(items, (item) => { item.visible = (item.condition === 1); });
It compiles to:

_.each(items, function(item) { item.visible = (item.condition === 1); });

So maybe I should start using braces when I don't want to explicitly return a value. But it looks so much cleaner the other way when you just want to do a simple one-liner. So we'll see...