DEV Community

Cover image for TypeLib JS (part 3) - Error debugging and conditional verification
Schemetastic (Rodrigo)
Schemetastic (Rodrigo) Subscriber

Posted on

TypeLib JS (part 3) - Error debugging and conditional verification

If you don't know what TypeLib JS is, in short, is a JS library that helps you to detect multiple types of data, it can detect NaN, Infinity, -Infinity, arrays, blobs, dates... and much more.

You can check the project page at: typelib.schemetastic.com

You can also get a great introduction to the library reading the first part of this series, Link here.


Another great feature that TypeLib has, is that it gives you the ability to debug TypeErrors. But to introduce you to that feature before, let me explain how you can use TypeLib to conditionally verify data.

.isIt() and .isNot() methods

Usually, when we want to verify data, we would use conditionals... e.g.

if (
    typeof params.tasks == "string" ||
    Array.isArray(params.tasks) ||
    params.tasks?.constructor === Object
) {
    // Code to be executed if the data meets those types
}
Enter fullscreen mode Exit fullscreen mode

When we need to verify multiple types, conditionals easily can get too long and hard to read. TypeLib JS removes all the hassle by providing a way to verify one or multiple types of data in a semantic way.

Detecting one type of data:

// Using .isIt()
if (type(num).isIt("number")) {
    // Allows only number values, not NaN, Infinity, null...
}

// Using .isNot()
if (type(callback).isNot("error")) {
    // Allows any type of value except `Error`
}
Enter fullscreen mode Exit fullscreen mode

Detecting multiple types of data:

// The example above could be translated to:
if (type(params.tasks).isIt(["string", "array", "object"])) {
    // Code to be executed if the data meets those types
}
Enter fullscreen mode Exit fullscreen mode

As you can see, the methods .isIt() and .isNot() return a boolean, and they make it really easy to verify data.

the typeErrorIf function

Now that you know the methods .isIt() and .isNot() it will be easier for you to understand this function. With it, you can generate TypeError objects and throw them or catch them in a variable.

A general approach to do this, would be doing something like:

function addToDo(toDo){
    if (typeof toDo !== string || Array.isArray(toDo))
        throw TypeError("The `toDo` argument is expected to be a string or an array");
}

addToDo({});
Enter fullscreen mode Exit fullscreen mode

That's work that I'm pretty sure many wouldn't like toDo... 🥁... sorry, I saw the pun and I couldn't help myself... But! the typeErrorIf function helps you to achieve this in a one-liner, and is semantic also.

The syntax is pretty similar to the type function, but it adds one more chained method.

Throwing errors .throwIt()

The example Above could be done with typeErrorIf as simple as this:

function addToDo(toDo){
    typeErrorIf(toDo).isNot(["string", "array"]).throwIt();
}

addToDo({});

/*If the condition is met, then it will throw an error like this:

Uncaught TypeError: Unexpected type: object; The only allowed types are: string,array
*/
Enter fullscreen mode Exit fullscreen mode

See? You don't even need to write the error message even though you could, by passing inside the throwIt() method, an object like this:

typeErrorIf(toDo).isNot(["string", "array"]).throwIt({
    message: (theIssueType, expected) => `Nah nah nah, Really? ${theIssueType}? Next time you'd better send ${expected.toString().replaceAll(",", " or ")}`,
});

/*
Throws:
Uncaught TypeError: Nah nah nah, Really? object? Next time you'd better send string or array
*/
Enter fullscreen mode Exit fullscreen mode

And it would be a good practice that you'd add a cause to the error, it is very easy to do:

typeErrorIf(toDo).isNot(["string", "array"]).throwIt({
    cause: addToDo // This is the function
})

/*
Uncaught TypeError: Unexpected type: object; The only allowed types are: string,array
[...]
Caused by: function addToDo(toDo)
*/

Enter fullscreen mode Exit fullscreen mode

Adding a cause to the errors will generate a better stack trace that will be easier to debug.

Catching errors .catchIt()

If you don't want to throw the error, you could catch it in a variable and do whatever you want with it, log it instead of throwing it, send it to a DB to detect if your app produces TypeErrors, modify the object itself, throw it in a different moment.

let err = typeErrorIf(toDo).isNot(["string", "array"]).catchIt();

console.log(err);
// logs: TypeError: Unexpected type: object; The only allowed types are: string,array
Enter fullscreen mode Exit fullscreen mode

Support this project!

As you can notice, producing this content and this library requires a lot of hours of research and efforts. And this library is offered for free to everyone under the MIT license. But it would help me a lot if you give it a star 🌟 on GitHub, and if you like it, you can spread the word 📢 if you want to.

Link to the repo

Top comments (0)