Numbers
One of the things that I strongly dislike about JavaScript is its treatment of numbers. In JavaScript, you have one type of number, which has the range and precision of a 64-bit IEEE floating point value.
This has some nasty side effects, such as things behaving like integers when they are in the 52-bit mantissa and then suddenly behaving like floating point values. It also makes compilation very difficult.
Because this irritates me so much in JavaScript, it was one of the first things that I looked at in Dart. I was pleasantly surprised. There are two kinds of numbers in Dart: integers and floating point values.
As with Smalltalk, if integers become too big to be represented in a single register, they are transparently replaced by objects that use an arbitrary precision representation. This means that aside from performance issues, there is no need to worry about the size of integers. The compiler and run time are free to use integer arithmetic when available and fall back to calling out to library functions when necessary.
You can see this in the JavaScript translation of a simple Dart function. This Dart function:
var i = 42; void addToI(x) { i += x; }
becomes this in JavaScript:
function addToI(x) { $globals.i = $add$($globals.i, x); }
The $add$ function is defined in the support functions for Dart, and should do the correct thing. Unfortunately, this is where theory and practice start to diverge. In the current version, this works correctly in the Dart VM, but in JavaScript it exhibits JavaScript semantics.
If you display the result of var 2305843009213690000 * 2305843009213690000 in the Dart VM, then you get 5316911983139645266232083416100000000; while in a JavaScript VM you get 5.316911983139646e+36. You can see the loss of precision by subtracting 5316911983139645266232000000000000000. If you run this in the Dart VM, then you get 83416100000000. If you run it in another browser, then you get 0.
The difference between 83416100000000 and 0 might be unimportant to Google, but for the rest of us it often is. Of course, Dart is currently still a beta release, so some bugs are expected. Hopefully the final version will do a better job...
Type Checking
Variables in Dart are optionally typed. This notion should be familiar to developers who have used Objective-C or StrongTalk. As a dynamic pure object-oriented language, there is no need for explicit type annotations, as every operation can be checked at run time. In Objective-C, the id type fills this role, allowing you to just say "this is some kind of object," instead of "this is an instance of this class (or a subclass)."
The type annotations do not alter the semantics of the program. This is a very important trait for optional and pluggable type systems. Adding annotations simply helps with static analysis of the program.
If, for example, you write a function that works only when passed numeric types, then you can annotate the arguments with 'num' (meaning any integer or floating point type), and the compiler can check that it is never called with arguments of the wrong type (as long as the caller types are also annotated). When you compile in checked mode, all these type annotations will be checked at run time as well. This imposes a fairly significant performance hit, but is useful for debugging.
The more type information that is provided, the more helpful the compiler can be. Unfortunately, Dart does not provide any type inference, so your only choices are static type annotations or run-time type checking. This is a shame, and somewhat surprising for a modern language. Go includes type inference and these days even C++ does.