JavaScript++ vs. TypeScript

Short version: TypeScript is not type safe.

JavaScript++ has been around for over a year longer than TypeScript and used to be essentially the same thing (everything from classes/static typing to being a superset of JavaScript to debugging with source mapping) without the Microsoft branding. The difference is that JS++ listened to feedback and was redesigned and refined over the course of three years, while Microsoft ran riot and just wanted to get to market.

Most importantly, in JavaScript++, you do not need to add type annotations or provide the compiler with type “hints” for each JavaScript library. You can just plug in your existing JavaScript libraries and still get the benefits of the JS++ type system; while TypeScript requires you to manually read through library code, write out type definitions to help the compiler, and then risk having to go through all of that again each time the library is updated. For most developers and organizations, this is a time-consuming, expensive, and unrealistic expectation.

After all this hard work, you’re still vulnerable to the pitfalls and failures of TypeScript. The following code should not pass a type check because getElementsByTagName returns HTMLCollection in Gecko and NodeList for every other browser engine:

[js]var foo:NodeList = document.getElementsByTagName("*");[/js]

However, we can still make the test pass simply by adding type annotations to the DOM and signifying to the compiler that getElementsByTagName always returns NodeList for simplicity’s sake. Unfortunately, that creates a false sense of security, and we’re stuck with scenarios which lead the programmer to expect the following code to return true:

[js]document.getElementsByTagName("*") instanceof NodeList[/js]

The above will return true in every other browser but Gecko-based browsers (namely, Firefox) because, once again, Mozilla insists HTMLCollection should be returned as defined in the specification. The plot thickens and the programmer is now writing code and using the methods of NodeList which result in runtime TypeErrors. In most cases, bugs like this can be fixed, but Mozilla has filed this bug as WONTFIX for the aforementioned reason:

https://bugzilla.mozilla.org/show_bug.cgi?id=14869

If Mozilla wanted to fix it, they would have fixed it in 1999 (when the bug was first filed).

Nevertheless, even in a perfect world where this were consistent across all web browsers, it doesn’t address the underlying problem: there are too many inconsistencies across browsers, too many edge cases leaving a language/compiler perpetually in the “beta” stage, and there is just enough infighting and disagreement amongst browser vendors to prevent the building of a solution that’s robust and enterprise-ready.

Static type checkers only check types at compile time; they do not simulate or evaluate code. Therefore, it’s impossible to distinguish a Number from NaN. In JS++, when you want an int, you get an int, and not a number of type Float, NaN, Infinity, etc.

Microsoft TypeScript can be downright dangerous because it gives you a false sense of security, which is worse than having no security at all. I’m surprised Microsoft allowed their brand to be associated with this. Anders Hejlsberg has my highest respect; I began as a programmer on Delphi 3, and I learned C# when it first came out and fell in love with it. I’m all too familiar with how Gates personally recruited him to join Microsoft. However, he is not the right person for this job because he simply does not have the requisite experience to draw upon to create the best possible developer experience.

Ultimately, it’s your choice which language you use, but if you’re choosing between JavaScript++ and TypeScript, you should be sure you’re choosing a language that’s ready for today but will keep up with the demands of tomorrow.

Inline Callbacks: More Optimized, More Refactored

What’s cool here is that, unlike traditional inlining, we aren’t just performing inline expansion of some monomorphic function. Instead, via callbacks, we are able to define entire subprograms and sequences of statements to execute. This grants us amazing expressive power. We are able to write clear, readable code without sacrificing performance. Take this very simple example:

JavaScript++:
[js]
runTwice(function(){ log("Hello World!"); });
[/js]

Java:

[cpp]
for (var i = 0; i < 2; i++)
{
log("Hello World!");
}
[/cpp]

Both snippets of code are attempting to log a message twice. However, the JS++ code is much more readable.

At first glance, it would appear the JS++ code will run slower. After all, it’s dealing with two function calls versus the zero for Java. However, let’s take a closer look at how runTwice is actually defined in JavaScript++:

[java]
inline void runTwice(inline void callback())
{
callback();
callback();
}
[/java]

After the compiler desugars and performs inline expansion, our original code becomes:

[js]
log("Hello World!");
log("Hello World!");
[/js]

What you are seeing is that there is ZERO performance penalty.

The benefits are enormous from readability to refactoring to maintainability. Now that you’ve had a brief introduction of inline callbacks and the vast expressive power they offer you, let’s dive into deeper, more real-world examples.

Continue reading Inline Callbacks: More Optimized, More Refactored

Semantic Inference for Succinctness

While working on JavaScript++, it occurred to me the programs were becoming verbose a la Java. For example, to define a pure function, we might write:

pure function foo(int bar, int baz) {
    // ...
}

While JavaScript++ will infer whether or not a function is pure, I could not find it in my heart to do away with the “pure” keyword. Why? Because, in large-scale applications, it is important to be able to apply explicit restrictions. If it is desired for a function to be pure, we do not want a team member accidentally introducing side effects later on.

Continue reading Semantic Inference for Succinctness