Closed dvv closed 13 years ago
This seems more appropriate for a a library. CS usually tries to keep this kind of fluff outside of the language unless it's a really common pattern. This doesn't seem like anything I would ever make use of, and I know it's something I never have.
edit: I'm going to mark this as a wontfix
, since I'm sure jashkenas agrees, but I'll leave it open so that it at least passes under his nose. And any other feedback in support of or against this issue would help.
So how do you test the type of a value?
Type-checking isn't really a common pattern in JS because of its loose typing paradigm. You should just be duck-typing. The only time I personally use typeof
is for undeclared reference testing, but CS solves that with its existence (?
) and safe property access (?.
/?[]
) operators. What's the specific problem you're trying to solve?
I might have used the wrong wording to explain my point, but I did exactly meant seems
is for duck-typing. I want to completely avoid relying on typeof
(and may be instanceof
) in my code and would recommend to do so the others.
But type (duck- or not) checking is certainly of value. I've much code which deals with values which can be string/array/function, and the code behavior is different in these cases. E.g. if function -- call it and use the return value, if string -- reference an object property, if array -- drill down into object, steps beings items of the array.
I do know CS is trying to be JS engine neutral, and pure -- but the suggested and recommended way for people to start using duck-typing is hardened by the lack of means in the language. The dangerous stuff should be hidden and hard to call, while the recommended way should be clear and easy to use. I won't suggest to replace typeof
since there might be code depending on it, but to say the truth it should be replaced, imho. Or, a new type tester.
I also find it quite natural for literate programming to associate seems
to duck-typing test, otherwise I'd have suggested introducing ducktypeof
:)
Eh, it seems you have a different idea of "duck-typing". I didn't mean trying to determine some "type" (whether it be the internal [[Class]] or whatever) of an object by what properties it has, but writing your program to only depend on an object that has certain properties. Do you understand now what I meant? It would probably help if you posted a gist containing your problematic code.
I understand your point, but I'd like to have robust "give-me-the-type" tool in the language. typeof
and instanceof
are not such.
We don't have means to do for (var i in array) {}
. I guess this restriction has rationale to not allow doing bad/deprecated things. We do have for own k, v of hash
to ease robust iteration over own props. These are signs of that CS tries to teach the best practices, ain't it? typeof
and instanceof
are not robust. By kicking them CS could promote recommended way of type checking.
This issue is not limited by a particular problem, this is an attempt to make CS promote good code style, the latter being recommended by JS coders themselves.
As an example I'll soon be spawning a repo here which has many to do with typing.
What compilation are you expecting?
I'd expect typeof
overloaded behind the scene, to return the right string.
So CS typeof X
compiles down to __typeof(X)
defined once for the source file just like for __hasOwnProperty
. __typeof
can be a simple when/then
, reusing underscore _.isXXX()
logic which seems pretty useful yet non-bloaty
So: t = typeof /node.js/ # t = __typeof(/node.js/); console.log 'well done CS' if t is 'object'
The plain JS' typeof
can still be accessed via backticks.
And may be seems
keyword to put syntactic sugar:
console.log 'good' if 2 seems 'number' # if _.isNumber 2
console.log 'better' if (new Number(2)) seems 'number'
console.log 'cool' if (new RegExp('v8')) seems 'object'
I'm afraid that Michael has this one down cold. This sort of operation isn't the kind of thing that gets added to CoffeeScript ... and even elsewhere in JavaScript it's not a great idea. The simple fact is that JavaScript has a very poor set of types, and there's very little good that can come out of trying to name them with strings -- the real useful typechecking is saying "is this object an arguments object or a real array" ... "is this object null or undefined" -- that sort of thing.
Closing the ticket.
Also, I remembered that I sometimes use
typeof callback == "function"for checking if I should call a callback. But that's the extent of the usefulness of
typeof
. michaelficarra: consider trying your code in Chrome/node.js to test if typeof /i-am-function-you-know/ == 'function'
.
jashkenas: "is this object an arguments object or a real array" == _.typeof(obj) in ['object', 'array']
== _.typeof = (obj) -> return 'object' if _.isObject(obj); return 'array' if _.isArray(obj); ... and so on all _.isXXX ...
Just don't see why so dense objection.
@dvv: Do I care? It's callable, which is exactly what I was looking for. I wasn't looking for an instance of Function
. You're still just missing this whole duck-typing thing...
You don't care of consistent behavior across the engines? Why?
Ugh, I do. I care that the value that I'm calling (using ()
) is callable. RegExps are callable in some implementations, and they will produce "function"
, consistent with my expectations.
Frankly, how do you yourself check that a value is a regexp, or a number, or a date? Mind to share your pattern of doing this with coffee-script?
Maybe this is a better way to explain it. Javascript doesn't have those things. It has objects, that's all. Some of those objects have a constructor
property of RegExp
. Some of those objects have an internal [[Class]]
property of Date
. Some of those objects produce "undefined"
when the typeof
operator is applied to them. Some of those objects produce true
when compared to the empty string with ==
. Some of those objects have their own hasOwnProperty
property. You need to test for the feature that you want to use. It's always dependent on the situation. There are no real "types". Hopefully you will get it this time.
edit: pedantics: please don't be pedantic about this post. I'm trying to get an idea across.
I see. I understand that in JS any object (except null?) can have traits of any "type-as-we-know-it-in-other-languages". An array being given a .match
property can pretend to be regexp etc. That is ok.
Now I see classes implemented in coffee-script -- this is the helper to deal with common pattern in JS, but admit JS has no classes (just like it has no types either), right? So imho classes in coffee-script ease the use of common pattern (classic inheritance) which people got accustomed to. And that is ok again.
Now despite JS has no types there are tasks to analyse of what flavor the object you are given. It really doesn't matter on what basis this flavor is determined -- duck-typing or not -- just means needed to classify what is object capable to do.
Now the chances high that people will you underscore.js to perform this classification. This library has close to complete set of duck-type testers _.isXXX()
. This is ok unless you already work in ES5 environment which has native implementations of most features for iterables and functions, which older engines miss. But in turn ES5 miss duck-type testers, and force people to reinvent their own. So those who rely on plain typeof
risk to write wrong code.
What I'm suggesting is to port _.isXXX
routines to coffee-script, so people could properly use duck-typing OOTB. If in coffee-script obj typeof XXX
compiled behind the scene to (_.isXXX(obj))
, and _.isXXX
were internally defined (like __hasProp
, __slice
et al.), we'd get consistent syntax plus robust duck-typing w/o any loss in readability.
Have sense?
Hi!
Having read http://bonsaiden.github.com/JavaScript-Garden/#typeof realized the cause of why I ago lost a day finding a bug in my node.js code -- could not imagine that
typeof /a/ is 'function'
.The proposal is to introduce in coffee the special operator
seems
which should return the string denoting the type of operand in confident way. The realization could be borrowed from underscore.js.E.g.
2 seems 'number' is (new Number(2)) seems 'number' is true
.What do you think?
Best regards, --Vladimir