
Type Checking in JavaScript - dmitri1981
http://techblog.badoo.com/blog/2013/11/01/type-checking-in-javascript/
======
marijn
Well, let's see

    
    
        var mostRecent = '';
    
        if (type(c.messages) === 'array' ||
            type(c.messages[0]) === 'object' ||
            type(c.messages[0].text) === 'string') {
            mostRecent = c.messages[0].text.substring(0, 30);
        }
    
        return name + ': ' + mostRecent;
    

.. apart from the fact that he probably meant && instead of || in that
condition, we've also now got a system that silently swallows errors. Bugs can
lurk in it without any more symptoms than producing empty strings where more
interesting strings were expected.

I much prefer my systems to crash when a programmer made an error, and do so
noisily and detectably, so that the problem can be fixed. I also prefer the
actual logic of my code to make up more than 20% of the lines. If you're going
to add boilerplate type checks all over, the signal-to-noise ratio gets really
bad.

So don't do this. Use Typescript if you want to check types.

~~~
jonbretman
Firstly good spot on the '||' instead of an '&&'. Will fix that now.

Secondly I completely agree about wanting a program to crash noisily and
detectably in development, but in production I would prefer that the error is
handled and the user can continue to use the app.

Finally I also agree that if type checking is really important to you, a
compile to JS language like TypeScript or Dart are the best options. The
techniques / approach I am discussing in this article are really for people
who already have a large vanilla JS code base or want to learn a bit more
about types in JavaScript.

~~~
vladiliescu
Just wanted to add that TypeScript is backwards compatible with JS, so having
a large vanilla JS code base doesn't really matter - it's already valid
TypeScript code, so you can go and start adding type annotations and whatnot.

------
nailer
I use 'kind' from Agave for this. It uses the same technique
(Object.prototype.toString() plus edge case handling) but ships with lots of
units tests to prove it:

[https://agavejs.org](https://agavejs.org)

    
    
        ### Numbers
    
            kind(37) === 'Number'
            kind(3.14) === 'Number'
            kind(Math.LN2) === 'Number'
            kind(Infinity) === 'Number'
            kind(Number(1)) === 'Number'
            kind(new Number(1)) === 'Number'
    
        ### NaN
    
            kind(NaN) === 'NaN'
    
        ### Strings
    
            kind('') === 'String'
            kind('bla') === 'String'
            kind(String("abc")) === 'String'
            kind(new String("abc")) === 'String'
    
    
        ### Booleans
    
            kind(true) === 'Boolean'
            kind(false) === 'Boolean'
            kind(new Boolean(true)) === 'Boolean'
    
        ### Arrays
    
            kind([1, 2, 4]) === 'Array'
            kind(new Array(1, 2, 3)) === 'Array'
    
        ### Objects
    
            kind({a:1}) === 'Object'
            kind(new Object()) === 'Object'
    
        ### Dates
    
            kind(new Date()) === 'Date'
    
        ### Functions
    
            kind(function(){}) === 'Function'
            kind(new Function("console.log(arguments)")) === 'Function'
            kind(Math.sin) === 'Function'
    
        ### undefined
    
            kind(undefined) === 'undefined'
    
        ### null
    
            kind(null) === 'null'

------
tomcdonnell
Here's how I do type checking in Javascript.

    
    
      function doStuffWithAVarietyOfParameters(s, a, b, i, ni, p)
      {
         var f = 'contractCategoriesAndAddExpandButtons()';
         UTILS.checkArgs(f, arguments, ['string', 'array', 'boolean', 'int', 'negativeInt', 'Particle']);
      
         // Do stuff.
      }
    

For functions with many parameters, I like to pass the parameters inside an
object and give the keys descriptive names.

    
    
      function doStuffWithAVarietyOfParameters(o)
      {
         var f = 'contractCategoriesAndAddExpandButtons()';
         UTILS.validator.checkObject
         (
            o,
            {
               arrayParam      : 'array'      ,
               boolParam       : 'boolean'    ,
               nullOrFloatParam: 'nullOrFloat',
               particleParam   : 'Particle'   ,
               positiveIntParam: 'positiveInt',
               stringParam     : 'string'
            }
         );
      
         // Do stuff.
      }
    

Both functions will throw an exception if the arguments list is not as
expected. The code can be found via the links below.

[https://github.com/tomcdonnell/lib_tom/blob/master/js/utils/...](https://github.com/tomcdonnell/lib_tom/blob/master/js/utils/utils.js)

[https://github.com/tomcdonnell/lib_tom/blob/master/js/utils/...](https://github.com/tomcdonnell/lib_tom/blob/master/js/utils/utilsValidator.js)

I do type checking similarly in PHP.

[http://tomcdonnell-tech.blogspot.com.au/2011/09/favourite-
ph...](http://tomcdonnell-tech.blogspot.com.au/2011/09/favourite-
phpjavascript-functions.html)

------
kashif
Always been interested in things like these. Did something similar with python
decorators, just for fun -
[https://github.com/kashifrazzaqui/pyutils](https://github.com/kashifrazzaqui/pyutils)

------
slig
Who would've thought that after years of cursing them for spamming me, I would
read something interesting on their tech blog.

~~~
joshguthrie
Thanks for summing up my thoughts.

------
voidr
Firstly: they could just start using TypeScript if they really care that much
about type erros, since TS is a superset of JavaScript they can start using it
with their existing code, so there is no excuse not to use it.

Secondly: it's ridiculous that their way of handling type errors is by just
silently hiding them. They could be making a lot of errors that will become
really hard to find this way.

Thirdly: performing type checking on runtime in JavaScript is just stupid,
things like this could be performed at "compile time" with TypeScript or the
Google Closure Compiler.

------
ankurdhama
Basically adding "compiler bits" into your dynamically typed language
application code.

~~~
CmonDev
Fixing the symptom.

------
johnnymonster
It appears you are doing this because you are never really sure what sort of
data is being sent to your application. I would dump this sort of idea in
favor of schema validation. if you are going to get data from a client
application where the client developer can screw up the data, why not just
validate the data as a whole before accepting it then you know your structure.

I really just can't stand all the type checking all over the place, it makes
the code feel like all your reading is type checking and not the real logic of
what is going on in this function.

Additionally, returning an empty string when i mess up a data structure is
horrible for debugging. I would have to actually go into the code now to
figure out why an empty string came back instead of processing as I thought it
should.

if your really worried about exposing errors to the end user. wrap that whole
thing up in a try catch block instead, log an error and don't display anything
to the end user.

~~~
macspoofing
>It appears you are doing this because you are never really sure what sort of
data is being sent to your application.

He's doing this because he wants type safety in his functions. If you have
that, you eliminate one source of bugs.

>I really just can't stand all the type checking all over the place, it makes
the code feel like all your reading is type checking and not the real logic of
what is going on in this function.

That's a big problem with his approach. It's not scalable, and you can't rely
on it (inevitably, developers will take shortcuts and you're going to have a
hodgepodge of type checks littering your code). He might as well use
TypeScript or Dart or Google Closure Compiler.

>I would have to actually go into the code now to figure out why an empty
string came back instead of processing as I thought it should.

Problem number two with his approach. He doesn't actually have compile-time
checks which is where you want your type-checks to be. Instead it's all run-
time (and he ignores the errors), which raises the question, what the heck is
he actually gaining from all this?

Again, he should just use TypeScript or Dart or Google Closure Compiler.

------
philbo
I've contributed to a little JS lib [1] that takes a similar approach, but
expands all of its predicates with two modifiers: a `maybe` modifier that
tolerates null and undefined; and a `verify` modifier that throws if the
predicate returns false. I've found it quite useful for eradicating some
common boilerplate from my code.

e.g.:

    
    
        var check = require('check-types');
        check.unemptyString(''); // returns false
        check.maybe.unemptyString(); // returns true
        check.verify.unemptyString(''); // throws Error
        check.verify.maybe.unemptyString(); // doesn't throw
    

[1] [https://github.com/philbooth/check-
types.js](https://github.com/philbooth/check-types.js)

------
hbbio
Typechecking JavaScript is feasible. But will be really hard in practice.

We have worked for years on the Opa technology, cf.
[http://opalang.org](http://opalang.org). Opa is a typechecked language with a
JS syntax that compiles to JavaScript. Unlike JS though, the semantics of the
language borrows to functional programming languages, to ensure the type
system is sound and type checking feasible with almost full type inference.

Opa does more than type-checking to JS, but even if you just want to typecheck
JS, basically you should look to design and implement a new programming
language, with a syntax as close as possible to JS but with proper semantics
and then that compiles to JS after type-checking. You could add a set of tools
to help port actual JS code to this new language.

------
mneary
With Typical[1], I took a different approach enforcing types on the functions.

[1]:
[https://github.com/mattneary/Typical](https://github.com/mattneary/Typical)

~~~
rimo
The approach is interesting but the syntax makes it hard to use. Why not make
the first arguments the types like one would expect?

~~~
mneary
I went back and forth with that. I think I went with postfix because there
exists another syntax which looks prefix:

    
    
        T([Number, Number])(function(x) { return x; })
    

For this method, a function type is defined and then serves as a constructor
that accepts a function as argument.

------
ceautery
A simple "constructor.name" query covers most of this. You still need edge
case checkers for null, Nan, and Infinity, but...

    
    
      function type(a) {
        var t = a.constructor.name.toLowerCase();
        return t.match(/^html/i) ? 'element' : t
      }
    

...handles the rest. Still, I liked this post quite a bit; it shows pretty
clearly how odd type checking can be in a loosely typed language.

------
jtfairbank
Sounds great! Looks like you can find similar functionality in underscore.js,
although they ask you to do the checking explicitly, ie `isBoolean(true)`.

------
stevecooperorg
Great solution -- by the end, that final 'type' object starts to look good;

    
    
       type.isNumber(4); // true
    

And it'd be easy to add validation versions, too, which might help clarify the
types as one call per parameter;

    
    
       type.ensureIsNumber(myParameter); // throws exception if not a number
    

which might help your code fail faster.

------
k__
What's with the obsession about (static) typing?

I have written code in untyped languages all my life and it has never been a
problem for me.

The only problem I see with bigger JavaScript apps is the callback-hell.

Funny thing is, most to-JavaScript languages focus on the type aspect.

If I could write linear asynchronous code everything would be much more
readable after coming back to some code a few months later.

~~~
mattmanser
But have you used statically typed langauges? Unless you've used _both_ you
won't be aware of the advantages.

The big one for me is inheriting other people's code bases, in dynamic
languages they're a complete and utter nightmare, especially when written by
incompetent programmers, which seems to make up a worryingly large number of
programmers. Or someone just learning and not aware of conventions.

You just can't assume a method or function actually does what it says it does.
Or returns what it says it does. And you can't even see what it's expecting or
what things are being passed to it. You have to fine-toothcomb the method, it
slows you down massively.

I have worked on a fair few bad code bases now and luckily for me the majority
of that's been in static languages. It makes it _so_ much easier.

Some of the other advantages of static typing include:

1\. having incredibly good auto code completion

2\. never having to remember or look up a method signature

3\. to refactor massive chunks of code almost completely fearlessly

4\. to fix crap code without any fear of breaking anything else

5\. as long as you name your methods well, never having to annotate anything
mundane (depending on your audience ofc)

There are also other things like that tend to go hand-in-hand because they're
usually explicit, like not worrying about implicit conversion (apart from VB
with option explicit off).

I've used both quite a lot over the last 10 odd years professionally
programming and I've recently been thinking that I would actually prefer a
mix, static typing on boundaries like method entry and new object declartion
and dynamic everywhere else. I know little about compiler or language design,
so I'm not sure it's even possible. C# kinda gets close with the var keyword,
but the various disadvantages of static typing still rear their head quite a
lot.

As a slight aside, People on HN always seem to talk as if they only write new
programs, not maintain old ones. Am I the weird one for frequently having to
pick up code that was written by someone else? Who often had coded themselves
into a corner and then made up some excuse as to why they couldn't keep the
client anymore?

~~~
k__
I had to do some stuff in Java at university, it felt too clunky most of the
time. :\

When using libraries, their functions always wanted their arguments to be some
strange classes or implement some of their interfaces, which always seemed
like big overhead to me.

Stuff like Smalltalk, PHP and JavaScript felt much faster in development
speed.

~~~
ufo
Thats because Javas has a clunky type system and bloated libraries full of
design patterns. In languages with better support for higher order functions
the bit about needing to pass a strange class is much more lightweight.

IMO, real advantages of dynamic typing vs static typing are

* Simplicity. You don't need to learn a complex type system to start coding.

* Flexibility. Dynamic type systems don't stop you from doing useful things ike polymorphism and generics. In a static type system those need to be build in from day 1.

~~~
danbruc
Completely disagree. Lazy developers not willing to learn a language can not
count as argument against statically typed languages. This is a bit like
suggesting you should better walk across the country because than you do not
need to fuel your car or buy some kind of ticket.

And having to build more advanced type system features on top of a simpler
type system is hardly a good thing either - type theory is not trivial and
chances that you will get it wrong are large. Even experts in the field make
wrong decisions, for example array covariance in Java an C#. And even if you
get it right you will usually not enjoy (all) the benefits of compile time
type checking and fail only at runtime.

~~~
k__
When I had lectures about type-theory in university, it made me even more
confident in not using statically typed languages. Those whole
contra/covariant problems I read about seemed crazy to me :\

It felt like even the implementers of those type-systems didn't get it right.

------
rimo
You might want to take a look at [https://github.com/philbooth/check-
types.js](https://github.com/philbooth/check-types.js)

------
CodingFu
BTW, I've written a module for the Node.js with similar API:

[https://github.com/CodingFu/typeof](https://github.com/CodingFu/typeof)

