CoffeeScript is, in the end, just JavaScript with a nicer syntax. So the string-interpreted-as-number behavior is expected and normal. You write:
This behavior appears wrong to me since a String cannot be multiplied by a Number.
Yet, due to type coercion in JavaScript, a string can be multiplied by a number just fine. And, importantly, the result is correct!
Your options with regard to strict type-checking are:
- Using
typeof
and throwing an exception (or handling it some other way), as you do now.
- Doing nothing.
You're still writing JavaScript, so option #2 is a valid solution to most type concerns. For instance, most (all?) the functions in the Math
object accept numerical strings just as well as numbers.
For other types, the GIGO principle usually applies: Garbage In, Garbage Out. I.e. if the user of your code passes something completely incompatible, like an object, they'll get NaN
back. And that's their problem, really. Same as if you do Math.floor({})
or something.
However, if type-checking is absolutely necessary, you can at least slim your code down a bit:
foo = (x) ->
throw new TypeError unless typeof x is 'number'
x * 3
Note that the code throws a TypeError
, which is more appropriate for this situation, and that, since it throws, execution of the function is halted just as effectively as writing return
. So there's no need for if...else
branches.
You can generalize it a bit with a function, if you need to do this more often:
assertNumber = (value) ->
unless typeof value is 'number'
throw new TypeError("Expected a Number")
Or, better yet, check whether the value is numeric:
assertNumeric = (value) ->
if isNaN Number(value)
throw new TypeError("Expected a numeric value")
And use it like so:
foo = (x) ->
assertNumeric x
x * 3