TypeLib JS (part 3) - Error debugging and conditional verification
Tags: javascript, opensource, productivity, codequality
Published: 2024-03-01 16:35:44

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](https://typelib.schemetastic.com)

You can also get a great introduction to the library reading the first part of this series, [Link here](https://dev.to/schemetastic/introducing-typelib-js-simplified-type-detection-and-debugging-8bd).

---

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.

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

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:**

```js
// 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`
}
```

**Detecting multiple types of data:**

```js
// 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
}
```

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:

```js
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({});
```

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:

```js
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
*/
```

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:

```js
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
*/
```

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

```js
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)
*/

```
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.

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

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


## 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](https://github.com/schemetastic/typelib-js)