Javascript Type Gotchas
May 1st, 2010typeof null // -> object null instanceof null // -> TypeError: Can't use instanceof on a non-object. true instanceof Boolean // -> false true == new Boolean(true) // -> true true === new Boolean(true) // -> false
Needless to say, this is very annoying if you’re trying to be be careful with your types and just goes to show that not everything is an object in Javascript. Come back soon for my attempt at a solution.
May 28th, 2010 at 7:13 pm
You had me going for a few minutes… and now I understand the difference between the typeof and instanceof operators. :)
In javascript, a “type” is different from a “class” (the object it is an instance of). So “typeof” will only return whether it is a number, boolean, string, or object. The “instanceof” operator is meant to be used on objects, to figure out what kind of object it is. So…
typeof null
// returns “object” because this variable is technically a null object
null instanceof null
// well, “null” isn’t an object type (i.e. an type you defined with a constructor)
// I think what we meant was:
null instanceof Object
// returns false, because null is not an instance -> it is the lack of an instance
true instanceof Boolean
// returns false, because true is not an instance of an Object, it is a primitive type
// That explains the last two examples too.
Thanks for the lesson!
May 29th, 2010 at 12:04 am
Yep, you’ve basically got it Collin.
However, there are no such things as classes in Javascript. Rather,
instanceoftells you whether the left-hand side object is in the right-hand side object’s prototype chain. This is why(new String) instanceof String == trueand(new String) instanceof Object == true: bothStringandObjectare innew String‘s prototype chain. Granted, the same would be true ifStringwere a subclass ofObjectin a class-based inheritance system, but remember that Javascript uses a prototype-based inheritance system and there can and often are subtle differences.When you use the
newoperator on a function (sayString) in Javascript, it is essentially the same asString.call({}). That is, theStringfunction is being called with an empty object as itsthisvalue. Thisthis(excuse the pun) functionality means that you can have something akin to mixins.String.call(Number.call({}))should give you an object with both string and number methods. I haven’t tested this, so I can’t promise it works.So, returning to your conclusions from the examples, your explanations are spot on except that
nullreally isn’t an object. I believe it’s a mistake in Javascript to return"object"fromtypeof null. Instead, I believe it is a primitive, not an object, and should returnnull.The solution I was hinting at, and still need to blog about, is typed.js, a better, ‘replacement’ type system for Javascript. It will give you consistent, rational type information. For instance,
nullis always aNullTypein my type system.January 12th, 2011 at 1:06 pm
This seems to be relevant, it implements a strong type system in javascript:
http://sourceforge.net/projects/jtypesystem/files/
From the documentation:
test = FT(TString, TString, TString, TArray,
function(x,y,z){
return new Array(x,y,z);
});
/* Ok */
test(‘x’,'y’,'z’);
/* Not ok */
test(1,’x',’z');
January 12th, 2011 at 1:27 pm
Thanks, Peter, I hadn’t see that library. However, I think my (incomplete) typed.js library is a little nicer:
Of course they’re quite similar, so your mileage may vary. I guess mine is a bit more verbose, but things like named parameters mean that my error messages are quite nice.
You’ll notice that the error talks about type conditions because typed functions in my system can actually specify not just the simple type but rather the conditions based upon it, such as all sub-types of String, such as if you wrote your own RichString extension to String. The README has more about type conditions and implicit conversions (an implicit conversion is being done from the StringType types I provided to type conditions which test for simple equality with the type).
February 12th, 2011 at 9:08 pm
Cool, they look really the same, but I like your named parameters more. You also doing recursive type checking. (From a quick glance of your code). Yours is much more advanced. Catching errors were a problem. But you seem to have found a elegant solution.
I wrote mine to make working with higher order functions easier. It was a hack to make the typesystem of javascript stronger. I like to write my code in a functional style.
Good work and thank for sharing. If I used it in a project and extend it, I will leave you a message. Cheers.
February 13th, 2011 at 11:45 am
Thanks, Peter. You’re right that typed.js does do recursive type-checking. However, it was a quick hack to make arrays with subtypes work. I’ve been thinking about how to revisit it to make any type of collection work, whether based on generic objects or otherwise organized.
For example, I’d like to figure out whether multiple type parameters can be supported in an elegant way. I already use an array for type parameters but I haven’t yet figured out how to check each type parameter without requiring the object or its type object to hand its parts off to the checker. I’d like to avoid messing with Array, Object, and other standard parts of Javascript.
April 4th, 2011 at 11:49 pm
It would be interesting to implement a static typechecker for javascript. I am working at a project for which we are developing a framework inspired by reactive programming in javascript. Because the maintainability suffered under the amount of callbacks. We separated the output to the outside world (the calling of a function, which accepts a callback) from the input from the outside world (the result, which comes from the callback). And the processing functions between the inputs and the outputs should be pure. As consequence of this, concurrency arises naturally.
Types become more and more important in the framework.
Static typechecking would be very handy. But dynamic type checking with good error messages is a big step forward.
April 4th, 2011 at 11:56 pm
I’ve talked to some fellow Scala programmers about whether you could do this using Scala. At the simplest you can use Scala objects which represent Javascript code and can be converted to Javascript (such as Lift’s) but even cooler would be a DSL (and probably compiler plugin) which would let you program Javascript but actually have it be correct, statically-typed Scala behind the scenes. People tell me it’s possible…