At last Mascara gets some serious competition! Microsoft has released TypeScript, a tool with the same basic idea as Mascara: A superset of JavaScript with type annotations, based on proposals for future extensions to ECMAScript, but compiled to plain Javascript which will run in today’s browsers.
This is great news for the users of Mascara. It shows the approach taken by Mascara is sound and getting traction. More importantly, an alternative implementation reduces the risk of lock in. If you get dissatisfied with Marasca, you can (with a modest amount of conversion) shift to TypeScript and vice-versa. This makes Mascara a safer choice for a long-term strategy.
Furthermore this will provide some valuable cross-pollination of ideas between the different approaches. Just as Microsoft has obviously been inspired by Mascara, Mascara is going to copy all the best ideas from TypeScript!
Syntax differences
One caveat: The class and module syntax of TypeScript is based on different ECMAScript drafts than Mascara. Mascara is based on the original ActionScript-compatible proposal. A different (not ActionScript-compatible) syntax have since been proposed, and since major players are now behind the new syntax, Mascara will also go forward and also support this syntax. A beta with support for the new syntax is available. (The old syntax continues to be supported alongside.)
I expect the older ActionScript-compatible syntax will be deprecated at some point in the future. (Although feedback from Mascara users is appreciated – if compatibility with ActionScript syntax remains important, please let me know.)
I will document the differences in an upcoming post, but in short, the keywords “function” and “var” are superfluous when declaring class members, and constructors are identified with the keyword “constructor”. Example:
Old syntax:
class Volvo {
var licensenumber : string;
function Volvo(licensenumber : string) {
this.licensenumber = licensenumber;
}
function drive() : void {…}
}
}
New syntax:
class Volvo {
licensenumber : string;
constructor(licensenumber : string) {
this.licensenumber = licensenumber;
}
drive() : void {…}
}
TypeScript has some great ideas, some less great, and some limitations. Here is my subjective take. (It is based on a quick reading on the spec so it's not exhaustive, and it probably contains mistakes.)
Great ideas
Arrow-syntax in function types. This a natural extension of the arrow syntax for function expressions (which Mascara already supports). For example string=>bool describes a function which takes one argument, a string, and returns a Boolean. This is concise and elegant (and now supported by the Mascara beta).
Overloads. Allows declaration of multiple type signatures for a single function implementation. This is for example heavily used in JQuery, where the same function have different semantics and return different values based on parameter types. The union-type kind of solves the same problem, but overloads are a much cleaner solution.
Open interfaces: It is possible to declare an interface multiple times, thereby adding members to an already declared interface. This is a great idea!
Automatic fields: When using the attribute public or private on constructor parameters, a field is automatically created, which is assigned the value. Elegant and useful.
Automatically import window/DOM api In Mascara you have to explicitly write import browserapi to get the window and DOM-types in scope.
Dubious ideas
There are also a few ideas where I’m not convinced of the merit.
Members must be prefixed with this., even when accessed in methods of the same class. I am not convinced there is any benefit to this overhead typing.
The angle brackets “casting” syntax, e.g. <string>x. This could become rather ugly (visually) when combined with generics which also uses angle brackets. (This is not an issue for TypeScript currently though, since it doesn’t support generics.)
this in static functions refers to the Function prototype. This is kind of logical if you know the intricacies of the JavaScript object model, but basically it will mostly be s source of confusion and bugs. In Mascara it is simply not legal to access this in static methods.
Limitations
There are a some limitations (compared to Mascara) which may be due to it being a new less-mature product, or different design goals. The most important limitations as I see it:
Browser compatibility. TypeScript generated code uses some of never JavaScript features (like defineProperty), which is not supported by all browsers in normal use. (For example IE7 does not support defineProperty.) This is probably a deliberate design tradeoff. In contrast Mascara has as a primary objective that the generated code should work in all browsers. Web developers have enough to worry about as it is.
Generics. There is a somewhat kludgy support for typed arrays, but no general support for generics. My experience is that generics are needed for a type system to be sufficiently powerful for general use. (Microsoft should know this, just take a look at the elegance of Linq in C#, which would be unthinkable without generics).
Backwards compatibility. The support for old-style objects/constructors in the type system seem to be limited and not directly compatible with the class system. This again is probably a deliberate design choice. Mascara in contrast attempts to make old-style constructors directly interchangeable with classes, to make gradual upgrade from legacy JavaScript to Mascara smother.
No include mechanism. TypeScript generate a seperate output file for each input file, and require you to include each output file with a script tag. A benefit to Mascara is you can split the code into as many files you want, but still have them merged to a single file, so you avoid the hassle and performance overhead by downloading numerous smaller files.
Non-nullable types. No support for declaring non-nullabel types. This is sad, since nullable everywhere is the billon dollar mistake!
- No block scoping and no definite-assignment analysis.
- No support for constants.
- “Public” and “private” modifiers, but no “protected”.
- No support for destructuring variable declarations or destructuring assignments.
- No doc-comment.
- No array comprehensions.
- No support for yield.
- No multiline strings or multinline reqular expression.
While features like these are not as high profile than a type system, I think niceties like these overall makes for a much more pleasant coding.
Bottom line: TypeScript is great, Microsoft seems to “get it”. It is also seem to be not as powerful as Mascara, but then again I am biased. Feedback and opinions welcome as always (in email or comments).