I'm on Google's Dart team, so I'm naturally looking at it from that
angle/bias. Here's some random stuff that caught my eye, mostly
comparing it to Dart. I've only spent a few minutes skimming, so don't
take any of this too seriously...
No generics
I guess some types are better than no types at all, but
it's really rough to lose those. TypeScript does have built-in array
types and object types cover some of the "map" type use cases. But not
being able to define your own generic types is a drag. The docs say
when added, generics will work using type erasure, which is what I'd
expect given it's "compile to lightweight JS" style, but that can be a
pain too. It's nice to be able to do stuff with your type arguments at
runtime sometimes.
All types are nullable
Dart is the same way. Makes me sad in both
cases.
The type annotation syntax is nice
Almost every language with
optional type annotations (ML, Scala, F#, Kotlin, etc.) goes with
"postfix after a :. Dart tries to use C-style type annotations which
causes some nasty corner cases. I like what TypeScript has here,
especially the syntax for function types:
function takeCallback(callback : (n : number) => number)
{ ... }
Interfaces are structurally typed, classes are nominally typed
Makes sense given that
it's JavaScript, but it seems pretty neat. Being able to implicitly
implement an interface is nice. But TypeScript doesn't seem to let you
go the other way: given a class, you can't make a new type that's
compatible with it without concretely extending it because of the
brand stuff. In Dart, thanks to implicit interfaces, you can.
Best common type can fail
That means this is a type error:
[1, true]
You can overload in interfaces by parameter signature
This is really cool
because it gives you a way have more precise type inference flow
through a function call that does some dynamic type switching. For
example:
interface Doubler {
double(s : string) : string;
double(n : number) : number;
}
With this, when the compiler sees a call to
double, it can correctly give you a precise return type based on the
inferred argument type. What I'm not sure is how to actually implement
a class that implements that interface and makes the type checker
happy. You can't actually overload concrete methods, and my five
minute attempt to make it happy by dynamic type checking didn't seem
to work.
There's a dedicated syntax for array types
Makes sense since
there's no generics. It's also nice and terse, which is good, but I
personally prefer general-purpose generics over one-off special case
collections.
There's no implicit downcasting
One of Dart's more
unusual type system features is that assignment compatibility is
bidirectional: you can downcast without a warning. Aside from the
typical special case of assigning to/from any (dynamic in other
languages), TypeScript doesn't allow that. You have to type assert.
Personally, I like TypeScript's approach here.
Arrow functions and lexical this
This is just motherhood and apple pie. I like it. (Dart
has this too, and this is always lexically bound.)
Overall, it looks
pretty neat. If you want exactly the same JS semantics (good and bad)
but also want a smattering of types, TypeScript seems decent. It's
like Closure Compiler but with a better syntax.
If you want something
that's a more aggressive step away from JS's syntax and semantics,
then it seems like TypeScript isn't that.