# Why use it?

[![Github Repo](https://camo.githubusercontent.com/e83dfdfb23b69cd7cf6e7a77f6500eb4a01c12cc1adc08f3708fc3627f77abe5/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f73746172732f6d75736963712f756e777261706974)](https://github.com/musicq/unwrapit)[![npm package](https://img.shields.io/npm/v/unwrapit.svg)](https://npmjs.com/package/unwrapit)

Handling errors is never easy. Let's take a look at 2 cases.

## Unexpected Crashes

It's common to import some functions either written by other teammates or from NPM packages.

```typescript
import {plusOne} from 'lib'
// plusOne(a: number) => number

function handler() {
    const ret = plusOne(1)
    console.log(ret)
}
```

This `handler` function is so simple, yet it still has a chance to cause the program to crash.

How come? Well, based on the signature of `plusOne` we can't find any clue. If we look into the implementation of `plusOne` you'll find that it will throw an error when the given number is even.

```typescript
function plusOne(a: number) {
    if (a % 2 === 0) throw new Error('Given number is even.')
    return a + 1
}
```

Even TypeScript won't give you any hints that the function might throw errors.

You might want to add the return type manually

```typescript
function plusOne(a: number): never | number
```

But the truth is that even if you do this, TypeScript still won't warn you that the code might throw errors. Check the [TS Playground](https://www.typescriptlang.org/play?ssl=7\&ssc=9\&pln=1\&pc=1#code/GYVwdgxgLglg9mABABwDYgM4HkwFMAUAhgFyJggC2ARrgE4CUpeAbnYgD5mU22IDeAKETDEMYIiKIApIgBMiALxLEABnqIoAC1pwA7mVz6AorR218AcgDiMVknLU2MDIlx2AdBfpCRtXFBBaJEJEAGpEAEYBAF8BAQgEDChEP2SFFHRsPHwI7wB6PJFEAD0AfiA).

```typescript
function plusOne(a: number): never | number {
    if (a % 2 === 0) throw new Error('Given number is even.')
    return a + 1
}

const ret = plusOne(1)
//    ^? const ret: number
```

{% hint style="info" %}
If you still don't get it, replace `plusOne` with `JSON.parse`.
{% endhint %}

If we don't read the document carefully, or the document just doesn't mention this trivial and we don't test it out during tests as well, tragedy might happen.

## Try/Catch

Let's take a look at a more complex example

```typescript
import {getUser, getNewsForUser, getRelatedNews} from 'lib'

async function handler(userInfo: {username: string, pwd: string}) {
    let user
    try {
        user = await getUser(userInfo)
    } catch {
        console.error('cannot get user')
        return {err: 'cannot get user')
    }
    
    let news
    try {
        news = await getNewsForUser(user.id)
    } catch {
        console.error('cannot get news for user')
        return {err: 'cannot get news for user')        
    }
    
    let relatedNews
    try {
        relatedNews = await getRelatedNews(news)
    } catch {
        console.error('cannot get related news')
        return {err: 'cannot get related news')     
    }
    
    return {data: {news, relatedNews}}
}
```

In this example, we need to get a lot of data from somewhere, and each step relies on the result of the above step, so they are invoked sequentially.  We also want to provide fine-grained error message hints and return the function whenever an error occurs.

With these 2 problems in the mind, let take a look at how `unwrapit` solve this.

## Just unwrapit!

The idea of [`unwrapit`](https://github.com/musicq/unwrapit) is inspired by [rust](https://www.rust-lang.org/). The concept behind `unwrapit` is simple. Program crashes because of unexpected errors being thrown out, what if we **wrap** them up into a **box**, and then let users **unwrap** them?

Let's take a look at how to improve the above 2 cases by using `unwrapit`

**case 1: unexpected crashed**

```typescript
import {wrap} from 'unwrapit'
import {plusOne} from 'lib'

function handler() {
    const wrappedPlusOne = wrap(plusOne)
    const ret = wrappedPlusOne(1)
    if (!ret.ok) {
        console.error('error occurs', ret.err)
        return
    }
    console.log(ret.value)
}
```

**case 2: try/catch**

{% code lineNumbers="true" %}

```typescript
import {getUser, getNewsForUser, getRelatedNews} from 'lib'
import {wrap} from 'unwrapit'

const wrappedGetUser = wrap(getUser)
const wrappedGetNewsForUser = wrap(getNewsForUser)
const wrappedGetRelatedNews = wrap(getRelatedNews)

async function handler(userInfo: {username: string, pwd: string}) {
    const user = await wrappedGetUser(userInfo)
    if (!user.ok) {
        console.error('cannot get user', user.error)
        return {err: 'cannot get user')
    }
    
    const news = await wrappedGetNewsForUser(user.value.id)
    if (!news.ok) {
        console.error('cannot get news for user', news.error)
        return {err: 'cannot get news for user')  
    }
    
    const relatedNews = await wrappedGetRelatedNews(news.value)
    if (!relatedNews.ok) {    
        console.error('cannot get related news', relatedNews.error)
        return {err: 'cannot get related news')
    }
    
    return {data: {news: news.value, relatedNews: relatedNews.value}}
}
```

{% endcode %}

{% hint style="info" %}
For more usages, just head to **Recipe** section!
{% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://musicq.gitbook.io/unwrapit/intro/why-use-it.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
