Thursday, October 11, 2012

JavaScript Made Everyone Crazy

Nobody seems to be happy, nobody seems to understand it ... everyone is trying to change it, pretending to make it better ... and again, nobody seems to realize it has been here since ever, it has been working in any field, it does everything, and it keeps getting faster!

One Scripting To Rule Them All

As simple as that: Dart compiles into JavaScript so does Java, CoffeeScript, C, C++ and any LLVM compatible/compilable language via Emscripten ... and now TypeScript too ... how cool is that? As tweeted before, if every programming language can be basically translated into JavaScript which is already an extremely high level scripting language, don't ya think that maybe is not exactly JavaScript the problem ? Don't ya think maybe it's time to learn it rather than keep moaning about it ? Hasn't this language already demonstrated to be one of the most malleable, powerful, adaptable, reusable, recyclable, expressive out there ? So why everyone is trying to pretend this language is not good? Why everybody wants this language to be something nobody needed until now or something that different?

What Is Wrong With TypeScript

I don't know where to start here ... but I'll try to make few points based on examples, OK? Please bear with me, you'll get it too.

Type Inconsistencies

Ironically, this is the very first point. Consider these two functions:
// note that string is written lowercase
function primitive(s:string):void {
  console.log(s);
}

// note that String is written PascalCase
function wrapper(s:String):void {
  console.log(s);
}
Now, with this "revolutionary brand new language" I ask you two simple questions and you should be able to answer me without testing, OK?
  1. will this call produce an error? primitive(new String(""))
  2. how about this one? wrapper("")
The truth is: there is no way to enforce the usage of a wrapper ... a language born to put on a scripting language types, is not strict with types themselves. string accepts primitives only, those that typeof(s) === "string" but String accepts both primitives and wrappers ... so basically, the most basic problem about JS is still there and developers are not encouraged to understand the difference between new String and just "string", they will put String everywhere feeling like they know what they are doing ... they are using classes ... WOOOOOOOW! Even more funny is the usage of bool rather than boolean, so that even what you know about JS does not work anymore ... so I guess Bool would be at least available, right?
The name 'Bool' does not exist in the current scope
Exactly, Boolean is the wrapper for bool: congrats! What do you say? It was to speed up typing? ... that's why you wanted types, to write less? ... wait ... what?

Fake Security

If you believe that typed code means better code quality, you are wrong. Typed code usually means that the developer knows types in advance ... that's pretty much it. In this attempt, where code is not resolved runtime, only types are, the feeling you are safer than before is natural ... well, you are not
function wtf(s:string):number {
  return s.charCodeAt(0);
}
Above function contract is extremely simple for both input and output ... too bad TypeScript cannot do much when it comes to calling the function, understanding that maybe that input has no char in index 0 so that wtf("") will produce a lovely NaN able to screw the rest of the logic because guess what ... NaN is considered a number: congrats again, another problem kept with TypeScript! Anyway, the latter example shows that it does not matter if input and output types are OK, it matters the logic. The fact String#charCodeAt returns a number does not mean that using it is safe. Same thing is with function s(o:Object):string {return o.toString();} which can easily fail with an object created through a null prototype, you know what I mean? This cannot be solved during translation time ... sorry for that!

Getting Worst On Security

In order to maintain decent performances, TypeScript tries to translate potatoes in potatoes ... which means, not too much magic, neither 17.000 lines of JavaScript are needed to simulate something JS is not, both ES3 and ES5. This time, I am talking about private attribute in classes and here an example:
class Point {
  // private they say ...
  private test:bool = false;
  constructor(
    public x:number,
    public y:number
  ) {}
  method():number {
    return this.x * this.y;
  }
}

class ColoredPoint extends Point {
  constructor(
    x:number,
    y:number,
    public color:string
  ) {
    super(x, y);
  }
  method():number {
    return 2 * super.method();
  }
}
What I am going to show you, is the demonstration that private in TypeScript is the last thing ever you can rely on:
// a lovely colored point
var cp = new ColoredPoint(
  10, 10, "test"
);

console.log(cp.color); // test

// accessing the private property
// from an extend, so not from the
// class it has been defined private
console.log(cp[cp.color]); // false

// setting the private property
cp[cp.color] = true;

// funny enough, this would be the same
cp["test"] = true;

console.log(cp[cp.color]); // true
Et voilĂ , mesdames et messieurs, private in TypeScript is and will always be a lie, for the simple reason JavaScript is that highly dynamic language you don't want to learn which is highly dynamic indeed. If you know JavaScript, you know also how to make things truly private when necessary ... in a much more reliable, secure, and meaningful way than what is offered here.
Repeated History? This kind of attack to private properties, obj.pvt VS obj["pvt"], was possible with ActionScript 2 as well ( damn it ... was it 2003 or 4? can't remember ). Adobe in that case did something similar TypeScript, Dart, or CofeeScript are trying to do to JavaScript but with ActionScript 1: it added sugar on top that was giving nothing to the language. This was because AS1 could already represent basically everything AS2 was able to do (AS2 was based on ECMAScript 4 same as C#, Silverlight, Air, and AS3). Moreover, AS2 has never been safer, better, smaller, or faster. It has been actually an epic fail since it has been replaced by AS3 the year after which was incompatible with AS1 and the reason I have abandoned Flash development: nothing better, just more pain in the ass! Cross platform problems were still there but a whole new language and namespaces to learn ... WOHOAW, and goodbye! ActionScript 1 has been a great product and it was 99% like JavaScript. This language that made Flash the most powerful and popular plugin ever changed, and the plugin is slowly dying since that time indeed ... I hope JavaScript won't do the same because for more than 12 years it has been just awesome and is still there, today more than ever, catching up with everyday modern/real-world challenges and without a glitch!

Translated Parent Accessor

One thing TypeScript got right about classes! Thanks gosh it did not attach anything to the prototype or each instance such this.super() and similar bullshit ... well done! But suddenly, "le wild WTF appears": super in the generated JS code, is the function, the constructor, and not the prototype, so that any super.methodName() call is translated into ParentFunction.prototype.nethodName.call(this)! This means that every super call will perform two lookups and will not ensure that the parent prototype cannot and should not be redefined runtime ... is that what TypeScript would like to be compatible with? I hope no ... so that constructor a part, in this way, every method of every class is penalized with performances and only the constructor has direct access: potentially O(methods * eachClass) rather than just O(classes) prototype lookups.

The Increased Performance Myth

The funny thing about TypeScript, is that basically the only real and concrete advantage of typed languages, the cost free and great improvement performance speaking, is completely absent. Not only all these typed checks are performed during translation and never again, but the tiny abstraction of the syntax requires more code than needed, as more closures than needed, as more memory, operations, function calls than needed so, in few words, performance is worst than before. OK, is not as bad as the whole Dart library moved in mobile devices, but still slower than good old JavaScript with or without common, well known, libraries.

No Benefits At All

After this analysis of "the latest coolest hybrid version of JavaScript", I believe things are clear:
  • more to write because of types (that's OK), more to learn, because of a new behavior specified in a 0.8 draft (that's not OK)
  • no concrete advantages over common JavaScript and its well known shenanigans: DOM still a mess, wrapper VS primitives, undefined and null or NaN, operators and other stuff too ... just YAGNI sugar that supposes to make us happy and dunno why
  • new shenanigans as it is for every bloody programming language ... so we have to be careful with both TypeScript and double check the equivalent generated JavaScript to be sure things are OK and as expected for real: double learning, OMG!
  • performance is worst ... maybe JIT compilers could somehow take advantage of TypeScript generated code but I don't think so plus is more code than needed as it is for every translator: not optimized, rarely faster
  • we can have mapped source code with TypeScript, we cannot have double mapped source code to understand errors if we would like to chose a different minifier over the TypeScript generated JS code
  • more I haven't talked about ...

Not All Wrong Neither

I know this post looks like I am throwing stones to MS intent and effort over this TypeScript tool / thing / language / proposal / whateveritis but I am not, I swear. I love the direction Microsoft is taking since IE9 but I have also said, and it wasn't just me, that the Web needs something else which is not sugar. Cool tools for debugging are all welcome ... new tools for something that does not solve a thing are a waste of time. We would like tools to make the Web better for every browser, faster for every CPU, graphically shiny for every screen ... classes for massive apps won't help anyone to make this happen and we all have the proof today that JavaScript never needed classes to scale, what we need are developers that know the language, use it properly, and move the web forward, rather than being stuck with sugar and sugar and sugar and sugar ... IMHO!

Everyone Is Crazy

Scripting Languages suppose to be easy, expressive and powerful, and JavaScript is one of them. The fact it has no classical inheritance is driving people crazy since ever: they need classes, that seems to be the only way they can think programming ... meanwhile, we all created what is the Web today and is far away from perfect but it's a great place and it's getting better on daily basis. Look what has been done ... think if strict types and classical OOP was the missing thing ... look again, and now move forward with your next, awesome, JavaScript based thing that will simply work everywhere and will satisfy your expectations! Thanks for reading, appreciated.

35 comments:

koti said...

Nice explanation. I like it!

Anonymous said...

I cannot say that you are overall wrong - TS has some of the same problems that JS has (well it is a superSET of it) but your reasoning is somewhat flawed - after all, the languagues will be converted to assembler/bytecodes - so why not write everthing with just 0 and 1?

Roberto Messora said...

Sorry but you totally missed the point.
you made a clear and perfect technical review, I agree every single word.
but...
the reasons behind TypeScript (and not only) are simply others.
we can talk about adoption strategy: do you know how many potential Javscript devs are out there in the MS ecosystem, and how many of them are not interested in learning Javascript the right way trying to find a way to "translate" (yes translate) their c# programming knowledge?
we can also talk about large solution management, in a specific environment such as Visual Studio, and maybe all the next tools MS will ship around TypeScript (testing tools, refactoring tools, libraries...)
that's why TypeScript, right or wrong.

jandreas said...

Agreed on most parts, nice rampage anyway :-)

Anonymous said...

You missed the point

harou said...

Exactly my thoughts, thx for writing them down. It seems JavaScript will get screwed anyway because of ES Harmony :/

Boris said...

Nice post, but do not hesitate to throw stones to the standards too, because the classy structure of TypeScript is directly inspired of EcmaScript.next (ES6). So basicaly, it's javascript from the future...

Anonymous said...

The reason that everything "compiles to JavaScript" (and, probably, the reason that people have such a problem with JS) is that you can't get rid of it. JS is the new IE6... because every web site on the planet uses it, we can't correct its flaws, improve its syntax or move beyond it.

I'm not disagreeing with you - we should learn about how to properly program JS (how its inheritance works, avoiding its problems, doing without jQuery, etc), but I feel this is more of a pragmatic concern than a dogmatic one

njy said...

"JavaScript never needed classes to scale"

I think what what they was referring to was not that JS needs classes to scale, but that devs need classes to scale, as in "you can decide to do everything in assembler instead of Java or C#, yes, but you can also decide to shoot in your foot".

AndyB said...

Clearly, as with other technologies to evaluate, Typescript isn't the tool for you. On my part, it could very well be an effective addition.

I'm interested that you say performance will suffer. Why do you state this?

ncloud said...

Excellent points. Static typing is useful for performance and API discovery, and if neither of those two can be achieved by adding static types do a dynamic language, then it is fairly useless to do so.

Jeremy McPeak said...

I originally stated your analysis is wrong. A better word would be petty, at least for your first few complaints.

Type Inconsistencies

TypeScript rightly ignores the line between primitive values and wrapper objects. The distinction between a primitive value and a wrapper object is typically only used to determine the level of someone’s technical knowledge of JavaScript. Except for extreme edge cases, the distinction doesn’t change how we write JavaScript code. Why should it matter for TypeScript?

The String, Number, and Boolean data types in TypeScript are primitive data types, and they were named as such to replicate the data types found in JavaScript. Just like almost every other statically typed language, TypeScript provides the string, number, and bool alias keywords that map to their respective data type. Obviously, the difference in these data type/keyword pairs is Boolean and bool. However, there is nothing out of the ordinary in this pairing; the bool keyword is commonly used as an alias for Boolean.

Fake Security

TypeScript adds type safety. It ensures that the value or object you have is of the correct type. TypeScript, just like any other programming language, doesn’t save a programmer from bad logic.

Getting Worst on Security

JavaScript currently does not support privacy. One can somewhat emulate privacy by using local variables and closures, but it is impossible to create truly private members for a data type without incurring a performance hit until ES6.

Translated Parent Accessor

I cannot disagree.

Performance is Worst

I agree and disagree. Is it faster than just writing the JavaScript? No, but it will certainly be faster than using any library.

To be clear, I love JavaScript. My first, knee-jerk reaction to TypeScript was (and still is) “just learn JavaScript”. But if it came down to TypeScript, CoffeeScript, GWT, Dart, SharpScript, or any other “compile-to-JavaScript” language, I would pick TypeScript in a heartbeat.

Andrea Giammarchi said...

Jeremy ... no, I am sorry.

Type Inconsistencies ... TypeScript *has* different behavior with string or String as well as JS *is* different when you chose wrappers instead of primitives.

A wrapper can carry properties, as example, for string analysis is quite common, while a primitive cannot.
Wrappers are also greedier than primitives, memory speaking, so using new String rather than String *is* different, on performance too.

On Security
you say: "JavaScript currently does not support privacy" ... then you say isn't true unless you impact performance ... so it does, because we know that, right?

Dealing with a language and a syntax that let you feel there are private members is a disaster prone programming approach ... if we all know these cannot work, how can we trust them? How can we use them? What's the meaning of private then, and why!

Performance is Worst

I don't get your point ... you gonna end up rewriting entire libraries via TypeScript thinking now these libraries are anyhow better ... these libraries, rewritten in TypeScript, will be slower than original.

About your last sentence, yeah ... probably me too, typescript at least is closer to what ES6 will be, maybe, one day .. so if I have to chose between those languages, TypeScript would probably be my choice as well.

Shanimal said...

I think the point about strongly typed language contructs is missed here. You said that ES6 has "no concrete advantages over common JavaScript" imho the real advantages to ES6 are code completion, finding compile time errors and function calls running in scope of the object they belong to. The first can be somewhat achieved with self documenting code practices. I come from AS3. Code completion is based on the local scope and the inheritance chain, you can't pass a string value to something that syntactically expects another type and every call runs in the scope it belongs to. Nice intro, I agree, everything should be written in javascript.

Andrea Giammarchi said...

where exactly have I talked about ES6 in this post? ... this post is about TypeScript ...

Jeremy McPeak said...

Andrea,

I'm aware of the difference between primitive values and objects. My point is that we typically don't use wrapper objects. So while, yes, TypeScript does allow you to call String() as a constructor, are people really going to do that? No. It's a non-issue.

Even if it was an issue, someone would have to use String throughout their entire code base in order for new String("foo") to not result in a compile-time error.

My privacy statement was poorly worded. JavaScript does not have a true form of privacy, and we won't have true privacy until ES6. The best that we can emulate privacy incurs a performance hit.

With saying that, TypeScript has true privacy; it's just that it doesn't translate into any tangible privacy in JavaScript.

But is this really an issue? Private is private in TypeScript. A team developing an app in a TypeScript environment is bound to the language's rules. So what if it doesn't translate into privacy in JavaScript? They're not writing against the output, they're writing against the untranslated JavaScript.

I didn't suggest rewriting a library in TypeScript. I merely meant that code written in TypeScript is more performant that code using a library. Like it or not, a good portion (perhaps the majority) of people using a library don't know or understand JavaScript. The output code from TypeScript will execute faster than code using a library. It's a statement that isn't necessarily poignant to the discussion, as libraries and languages like TypeScript target to different sets of people.

Andrea Giammarchi said...

Jeremy my examples are created via TypeScript .. when you say private is private ... you are saying my examples should fail. These are not failing, private is not private, even in TypeScript. Use square brackets and try by your own ... not an issue, really ;)

Juan Ignacio Dopazo said...

I think you're over-thinking the issue with private. We're already marking stuff as private/protected in APIs (ie: http://docs.sencha.com/ext-js/4-0/source/Base.html#Ext-Base-method-own, http://yuilibrary.com/yui/docs/api/files/event-custom_js_event-target.js.html#l36) when they're not true privates and it's still useful.

Anonymous said...

I like trains.

Anonymous said...

Your grammer obviously has the same problems as your argument: "Not All Wrong Neither," which is a double negative not to mention other understanability issues. Just like you saying "nobody seems to understand it" which indicates we need to fix it. Is it not good that people are trying to fix it?

Andrea Giammarchi said...

@juandopazo I am not a big fun of things that are not what expected ... in your own thing you are polluting the prototype which means that `this.own('own', 123)` will screw the thing, right? That's not private in any case so don't call it private ... some developer might think is private for real and write weak code thinking it's safe.

Anonymous: I like trains too ... actually that's what I've thought as soon as I have read about this TypeScript thing :D

Anonymous 2 ... yes, my grammar is not perfect, so isn't JavaScript as well as any other programming language.

We don't need necessarily to fix JavaScript ... surely it needs updates and that's why ES5.1 is out and ES6 is coming.

We need to fix IT instruction if you want, 'cause JavaScript is still ignored at University level and all developers know is Java which *sucks* big time.

As developer, you should be flexible enough to understand different paradigms rather than make everything as the only thing you know ... Java .. moreover, if that's what you want, why even bother with this hybrid thingy, just go GWT and be happy, am I wrong?

Last, but not least, TypeScript is not fixing JavaScript ... at all! There is no fix, only an extra layer on top that might give you many undesired surprises ( and I find hilarious people are defending it at all costs even when private is broken at all levels ... is this improving or being blind? )

Andrea Giammarchi said...

on "all developers know is Java which *sucks* big time" I don't mean the language, the fact developers cannot think differently than that .. I have programmed in Java too, as well as C#, it's OK ... I like both (C# more) but then I can write equivalent shit in JavaScript without moaning every day ...

Andrea Giammarchi said...

@juandopazo apologies I might have misunderstood what you were talkign about .. if that translate into private methods inside a closure that's perfectly fine ... properties are a different thing thought ... isn't it ...

Juan Ignacio Dopazo said...

No, those are all examples of libraries out there that use methods in the prototype that get marked as private when they're not truly privates. It's private by convention only.

I've been trying TypeScript a bit and I mostly like it as a ES6 to ES5 compiler. The annotations part I'm still not convinced I like. One one hand I recognize that when writing libraries I usually document stuff like privacy, types of parameters, return types, etc. I even write tests for them. So I'm attracted to the idea of putting that into code that gets automatically checked while I develop. Checking callback signatures is really cool.

But on the other hand I've seen annotations abused in AS3, I can't stand class-focused development, and types sometimes get in my nerves when I want to reuse variables or do other things I'm used to do in JS.

So I'm ambivalent for now.

Deldeyn said...

When I first started using javascript I tried to do it the C#/C++ OO way - I got awful, awful code! I then learned to use javascript "properly" (I hope! ;-) and I've got less codr that's more efficient and hopefully makes sense.

Unknown said...

The only reason everyone is targeting JavaScript is because it is the only language that runs in every browser.

The language is in some senses remarkable - first class functions being the most significant of these, and use of prototypical inheritance (I'm familiar with Self, which introduced this, and does it much, much better).

However, with the heavily documented flaws in the language - which even its designer Brendan Eich acknowledges, it is hard to see how you can be so blind you can't see them.

OK, you can code around them, or avoid them. However, put them in the hand of inexperienced programmers and you get the mess you see on most site's JS.

Colin Jack said...

Interesting comments. I'm far more positive about TS, I like a lot of what it's trying to do with structural typing and so on.

Having said that I haven't yet had time to use it and it sounds like the devil is indeed in the detail (string versus String) and I fully agree that the bigger problems are the ones worth solving.


"Fake Security"

Without getting into DBC I think what they are doing here is what I'd expect.


"Getting Worst On Security"

I'm not as worried about that as I maybe should be, there is a potential confusion cost. Even in say C# you can use reflection to set private members.


"The funny thing about TypeScript, is that basically the only real and concrete advantage of typed languages, the cost free and great improvement performance speaking, is completely absent."

This I do disagree with. I'm from a .NET background but have been working with JS a lot too and do love (most of) it.

However what I miss with it is the self-documenting aspects you get with typing, and the ability to effectively use tool based refactoring. You can see a method expects an IFoo, you can directly navigate to it, and then you can directly rename one of the members on IFoo and know it'll ripple through the code. Thats definitely useful and can save time.

That's where I think TS has a decent story, not least as it is not forcing you to use typing and uses structural typing which to me look like it could be a much nicer than the approach C#/Java etc took (though not sure if structural typing will mean we get less refactoring benefits).


"// setting the private property
cp[cp.color] = true;"

Did you mean test here?

Shawn Lawsure said...

Two of the best benefits of TypeScript not mentioned here: 1) Code is easier to read and follow, partly because it is more similar to other languages, and 2) It is easier for not-so-expert developers. A lot of articles like this online are written by top-notch developers that underestimate how important the above two facets of programming are.

Anonymous said...

amen brother, with my jQuery, JS I've been able to create some very useful code that work across all of the major browsers and it all works.

learn the thing an be done with it. it's here to stay and no matter how much you cry, it'll still be there

nightcoder said...

Well yeah, I listen. And I guess we have to put up with it. But I strongly disagree with the term "programming language". It is a scripting language. HowEVER, as we can rely on machine translation from programming languages, it becomes almost useful.

So what's wrong with a scripting language. Just one thing... the most common bugs blow up in the user's face, and he/she is totally innocent. In a programming language (at least good ones), those families of bugs won't even compile.

Also, I get an IDE that doesn't bring me back to the 80's like a text editor does... but again, with something compiling the real deal into javascript, I'm on board.

But I will not like it. Ever. JS sucks. I mean... it was invented by Netscape... how scary isn't that?

Anonymous said...

Ahh...the old "you don't understand javascript, that's why you don't like it" argument.

Let's make COBOL the assembly language of the web and see how people feel.

Technologist said...

Compiling TypeScript to JavaScript is like C to Assembly ,, typed C does not mean that your generated Assembly is a safe by itself ,, but it ensures that you will generate a safe "structure" of Assembly
it just gives you a strict rules not to get bad structure of codes.
I liked the way TypeScript works.

Anonymous said...

Javascript itself is just like C++: it gives you enough rope to hang yourself several times over.

What is really needed is a language that compiles to Javascript, that is a subset of Javascript, that enforces good style, and doesn't allow the ugliest kinds of JS programming.

Mark Rendle said...

You seem to be championing JavaScript as this amazing language that we should all just learn properly, while at the same time criticising TypeScript for not fixing all the anomalies and inconsistencies that have plagued JavaScript for the last twenty-odd years. You can't have it both ways.

Andrea Giammarchi said...

I'm impressed by the netiquette ... no insults so far but before it gets worst, I am closing comments here before you take this too seriously and start some religious fight ... OK?

Here, have some fun with this post summarized via comics ;-)

All the best