Beginner's TypeScript #23
Tags: programming, beginners, typescript
Published: 2024-01-15 15:00:00

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pgzgdrpwoqlcss5pi0xx.png)

⭐ **Error Message: "X Is Of Type Unknown"** ⭐

We have a function named **somethingDangerous** which uses a conditional statement based on **Math.random()**. If the value from **Math.random()** exceeds **0.5**, the function will throw an error, leading to a roughly 50% chance of failure:

```ts
const somethingDangerous = () => {
	if (Math.random() > 0.5) {
		throw new Error("Oh dear!")
	}
}
```

We use a try-catch block to handle this error. However, there is an error message under error inside of the catch block:

```ts
try {
  somethingDangerous()
} catch (error: unknown) {
  console.log(error.message) // red squiggly line under error
}

// Hovering over `error` shows:
'error' is of type 'unknown'.
```

We will figure out how to understand why this error is happening and determine what changes you could make in the catch block in order to correctly log the error message.

👉 **Sulution**

The **unknown** type implies that the value contained in the **error** could be anything.

However, it is distinct from the **any** type.

While **any** turns off type checking on anything it is assigned to, **unknown** maintains type checking. This means we can narrow the value down to the type we anticipate.

➖ **Narrowing with as**

One option for fixing this issue is to use **as** to assert that the error is of type Error:

```ts
try {
	somethingDangerous()
} catch (error) {
	console.log((error as Error).message)
}
```

Using **as** tells TypeScript that we know better and it is wrong to think of the **error** as being **unknown**.

➖ **Conditional Checks**

For example, we can use **typeof** to make sure that **error** is an object and includes a **message** property:

```ts
try {
	somethingDangerous()
} catch (error) {
	if (typeof error === "object" && "message" in error) {
		console.log(error.message)
	} else {
		throw error
	}
}
```

This solution works but is not the most elegant.

Instead, we could use **instanceof** to check if **error** is an instance of the **Error** class:

```ts
catch (error) {
  if (error instanceof Error) {
    console.log(error.message)
  } else {
    throw error
  }
}
```

In this solution, the original error will be thrown if the **error** does not extend the base **Error** class. This works well because all types of errors, such as **TypeError** and **SyntaxError**, extend the base **Error** class.

Narrowing is a great way to handle try-catch blocks in TypeScript. If you encounter a situation where **x** is of type **unknown**, you can typically use type narrowing to resolve it.

For more complex narrowing, you can use the [Zod library](https://zod.dev/) (and check out my [Zod tutorial](https://dev.to/nhannguyendevjs/zod-typescript-first-schema-declaration-and-validation-library-1-2dl4)).

---

I hope you found it useful. Thanks for reading. 🙏

Let's get connected! You can find me on:
- **Medium:** https://medium.com/@nhannguyendevjs/
- **Dev**: https://dev.to/nhannguyendevjs/
- **Hashnode**: [https://nhannguyen.hashnode.dev](https://nhannguyen.hashnode.dev/)/
- **Linkedin:** https://www.linkedin.com/in/nhannguyendevjs/
- **X (formerly Twitter)**: https://twitter.com/nhannguyendevjs/
- **Buy Me a Coffee:** [https://www.buymeacoffee.com/nhannguyendevjs/](https://www.buymeacoffee.com/nhannguyendevjs/)