JavaScript Duck Typing – How to Use Without Checking Properties and Methods

duck-typingjavascriptpolymorphism

I know javascript uses duck typing and at first I thought this would make polymorphism easy compared to strongly typed languages like C#. But now my functions that take arguments are littered with things like:

if(myObj.hasSomeProperty())

or

if(myObj.hasSomeMethod())

or

if(isNumber(myParam))

etc.

This is really ugly to me. I come from a C# background and I find defined interfaces to be much better.

I'm wondering if I'm incorrectly attempting to apply strategies that are effective in statically typed languages and there's some better way to do this in javascript?

I know I could just not check, but tracking down javascript run time errors can be a nightmare since they don't always happen where the error is actually occurring in the code.

Best Answer

How do you use duck typing in javascript without always checking for properties and methods?

Simple: don't always check for properties and methods.

In Ruby, what you are calling is called "chicken typing". In a dynamically duck-typed, language, you simply trust that the caller passes you a suitable object. It's the caller's job to honor his side of the contract.

I know javascript uses duck typing and at first I thought this would make polymorphism easy compared to strongly typed languages like C#.

You are confusing multiple orthogonal axis of typing here. There are four orthogonal axis of typing:

  • When: dynamic typing (types aren't known and checked until runtime) vs. static typing (types are known and checked before runtime)
  • What: duck typing (types are based on behavior), structural typing (types are based on structure), and nominal typing (types are based on name)
  • Can you see them? explicit typing (the types have to be explicitly annotated) vs. implicit typing (types are inferred)
  • strong typing vs. weak typing – you might have noticed that I didn't give this one a catchy title nor an explanation in parentheses, that's because unlike the seven terms above, which each have a single universally-accepted precise definition, these two terms have about a dozen semi-widely used vague definitions that contradict each other; ideally you should avoid these terms altogether, and if you must use them, precisely define them first

Since you mentioned C#: it is mostly statically typed, but supports dynamic typing through the type dynamic, it is mostly nominally typed, but anonymous types use structural typing, and syntactic patterns (such as LINQ query comprehension syntax) can be argued to be either duck-typed or structurally typed, it is mostly explicitly typed but supports implicit typing for generic type arguments and local variables (although the local variable case is rather strange compared to most other languages, because you cannot just leave the type out, instead you have to give it an explicit pseudo-type var, in other words, if you want an implicit type, you have to explicitly say so). Whether or not C# is strongly or weakly typed is a matter of which definition of the two terms you use, however, note that there can be plenty of runtime type errors in C#, especially because of unsafe array covariance.

I know I could just not check, but tracking down javascript run time errors can be a nightmare since they don't always happen where the error is actually occurring in the code.

Debugging is not an easy skill to learn. There are, however, techniques to make debugging easier, e.g. the Saff Squeeze is a technique described by Kent Beck which uses tests and refactoring for debugging:

Hit 'em High, Hit 'em Low:

Regression Testing and the Saff Squeeze

Kent Beck, Three Rivers Institute

Abstract: To effectively isolate a defect, start with a system-level test and progressively inline and prune until you have the smallest possible test that demonstrates the defect.