What was the reason to define lower-case keywords for primitive types like Boolean, Number etc.?

Topics: Language Specification
Sep 25, 2013 at 2:05 PM
In some languages like Java, there is a clear distinction between, say, boolean and Boolean (primitive vs. wrapper type).

However, according to the TypeScript spec, the lower-cased keywords are just aliases for the actual types so for example the boolean keyword should just reference the Boolean type (though they are not 100% "compatible", i.e. functions accepting "strings" cannot be called with "Strings").

I was wondering why were these keywords introduced. Why didn't the team decide to go with full type names like for example ActionScript did?
Sep 25, 2013 at 7:56 PM
To clarify, boolean does not reference the Boolean interface you see in lib.d.ts. The primitive type keywords reference the primitive types, which are otherwise not named. These primitive types appear to have the members of their corresponding named interface types (e.g. values of the primitive type number appear to have the members of the Number interface).
Sep 25, 2013 at 9:31 PM
Ah, you may have just defined what "primitive types" mean for me :) This is the full definition as given in the spec:
The primitive types are the Number, Boolean, String, Void, Null, and Undefined types and all user defined enum types.
Without taking any assumptions (which might be a dangerous thing if you learn TypeScript with background in other languages), I thought that primitive types are defined just by their presence in that list. This is the first time I hear that primitive types are "not named" or special in any way - interesting but makes sense I guess.

So when I declare var a: string, it is of a primitive type, while when I do var b: String, it is of an object type? Is that right?

Final question: what if primitive types didn't exist in TypeScript and even basic variables used types like String, Number etc. What problems would it cause and why was it necessary to introduce primitive types? For example, Date doesn't have a corresponding date primitive type.
Sep 25, 2013 at 9:55 PM
So when I declare var a: string, it is of a primitive type, while when I do var b: String, it is of an object type? Is that right?
Final question: what if primitive types didn't exist in TypeScript ...
boolean is a good example to talk about. The JavaScript boolean type itself has no members; the only reason you can call things like hasOwnProperty on the value true is because it gets implicitly converted to an object for the purpose of that call. Accordingly, the TypeScript Boolean interface has no members:
interface Boolean {
Now, thought experiment time, we remove the notion of a primitive type and say that true is of the interface type Boolean and thus has no members (other than the apparent members it gets from the global Object interface). Then we write code like this:
var x = true;
x = { foo: 'hello' }; // OK?
The object literal provided is a subtype of Boolean, so the compiler would have to allow this for the same reason it allows assignments from HTMLCanvasElement to HTMLElement. You wouldn't want this to be allowed.

Date is a good counter-example, because you could actually get away with passing some mock object that had all the same properties as a Date object to some function that expected a Date (minus things that actually check the prototype). There's no counterpart for the primitive types -- 'x === true' is only true if x really is a boolean, not just some other object that has the same properties as true.
Sep 25, 2013 at 9:56 PM
Correct, though 'a' will appear to have the members of the String interface type for various purposes (ex property access, assignment compatibility).

There are areas in JavaScript where doing something to a number is semantically different from doing that same thing to an object type (ex typeof, or adding a property to a number). So it would get strange if that distinction did not exist and then because of structural typing we allowed anything with Number's properties to be assigned and used with number primitive values. Further, because number is more efficient than its boxed form (Number) there's another reason for the type system to understand the difference.
Sep 26, 2013 at 6:40 PM
These are excellent answers, thanks. Maybe it is described somewhere in the spec and I have just missed it.