Node.js Error Handling

Node.js Error Handling – TypeError

Moving along through our detailed Node.js Error Handling series, today we’ll be exploring the TypeError. Within the Node framework a TypeError indicates that a passed argument is not of the appropriate type. This method is used liberally throughout the built-in Node API modules, and should also be used within your own custom code to perform type checking at the top of of your functions and methods.

Throughout this article we’ll explore Node’s TypeError in more detail, starting with where it sits in the overall Node.js Error Class Hierarchy. We’ll also look over some simple, functional code samples that illustrate how both the built-in API modules, as well as custom modules, make use of the TypeError for type checking purposes. Let’s get to it!

The Technical Rundown

Most Node.js errors inherit from the Error base class, or extend from an inherited class therein. The full error hierarchy of this error is:

Full Code Sample

Below is the full code sample we’ll be using in this article. It can be copied and pasted if you’d like to play with the code yourself and see how everything works.

When Should You Use It?

As previously mentioned, the TypeError should be used to indicate that an argument is not the proper type for what the function/method expects. For example, if a string value is expected, the top of the function code block will perform some type check to ensure the relevant parameter is a string. If not, a new TypeError(...) instance should be thrown.

Many of the built-in Node API modules use TypeErrors. For example, here’s a snippet of the path.js core module:

The assertPath(path) function is called at the top of nearly every API method provided by the path module, as a simple check that the passed path argument is actually a string. In our example code we’ll use the path module’s parse(path) method to try parsing a string path and outputting the result to the console:

To test this out we’ll pass two values, starting with a normal looking unix-style path string of '/Error/TypeError/index.js', followed by a simple number of 12345:

Executing these test calls produces the following output:

The normal string argument works as expected and outputs the parsed path object. Meanwhile, the numeric value of 12345 throws a new TypeError indicating that the passed path parameter must be a string. Moreover, we can see from the detailed call stack that we invoked the parse(path) method in the path module, which itself invoked the assertPath(path) function we looked at above, which is what actually threw the TypeError during execution.

Similar practices should be used within your own custom code, as well. Here we’ve modified our Book class to perform some simple type checking for our setXYZ(...) methods. This will help ensure that the user cannot set improper value types for properties such as the title, author, or pageCount.

It’s worth noting that you’ll need to perform the proper type checking, depending on what kind of value you’re interested in. For example, if we just need to know if an object is a primitive type (like a string, number, or object) we can use the typeof operator, as seen in Book.prototype.setAuthor and others. However, the Book.publishedAt property is meant to be not only an object, but an explicit type of object — a Date, in this case. Therefore, we have to use the instanceof operator to perform more complex instance type checking.

As before, we’ll be performing two different invocations to test this, starting with a valid set of arguments passed to the Book constructor:

Executing this function creates a valid Book instance and outputs the object to the console:

However, for our second Book we’re slightly modifying the author argument by explicitly calling a new String(...) constructor, which is part of the ECMAScript API:

Executing this code throws a TypeError from the Book.prototype.setAuthor(value) method:

This is a subtle change, but it illustrates an important consideration that must be made when coding your own type checks. The Book.prototype.setAuthor(value) method only expects that the passed argument be of type string, as checked by the typeof operator. Therefore, the new String object that we passed in the createInvalidBook() function fails this check and throws a TypeError. In reality, we’d probably want to perform some more robust type checking and maybe conversion, to be able to get the primitive string type from a passed String object.

Airbrake’s robust error monitoring software provides real-time error monitoring and automatic error reporting for all your development projects. Airbrake’s state of the art web dashboard ensures you receive round-the-clock status updates on your application’s health and error rates. No matter what you’re working on, Airbrake easily integrates with all the most popular languages and frameworks. Plus, Airbrake makes it easy to customize error parameters, while giving you complete control of the active error filter system, so you only gather the errors that matter most.

Check out Airbrake’s error monitoring software today and see for yourself why so many of the world’s best engineering teams use Airbrake to revolutionize their exception handling practices!