Hello everyone.
Have you ever felt that Try/Catch is a bit inconvenient when developing an application in TypeScript?
I found an intersting video on YouTube that describes how to handle errors in TypeScript in a simple way.
I'm sharing insights from the video as a review.
If you have any other good alternatives to try/catch, I would love to hear them!
Defining the getUser function for error handling
First of all, I defined a simple getUser function to illustrate error handling.
It returns a new user with the given id.
const wait = (duration: number) => {
return new Promise((resolve) => {
setTimeout(resolve, duration);
});
};
const getUser = async (id: number) => {
await wait(1000);
if (id === 2) {
throw new Error("404 - User does not exist");
}
return { id, name: "Noah" };
};
const user = await getUser(1);
console.log(user); // { id: 1, name: "Noah" }
Error Handling using try/catch
Rewriting the previous code using try/catch, it looks like this.
const wait = (duration: number) => {
...
};
const getUser = async (id: number) => {
...
};
try {
const user = await getUser(1);
console.log(user); // { id: 1, name: "Noah" }
} catch (error) {
console.log("There was an error");
}
Problem with try/catch ①: It handles every error that occurs within the try block
The code below is not ideal.
Even though it's just a typo, "There was an error" is displayed in the console. I only want to handle errors that occur specifically in getUser within this try/catch block.
const wait = (duration: number) => {
...
};
const getUser = async (id: number) => {
...
};
try {
const user = await getUser(1);
console.log(usr); // ← There was an error
// ... (a lot of code)
} catch (error) {
console.log("There was an error");
}
Problem with try/catch ②: The Pitfall of Using let
Okay then, let's try to solve it using let
.
const wait = (duration: number) => {
...
};
const getUser = async (id: number) => {
...
};
let user;
try {
user = await getUser(1);
// ... (a lot of code)
} catch (error) {
console.log("There was an error");
}
console.log(usr); // ← ReferenceError: Can't find variable: usr
I got an actual error from the typo, but this code is still not ideal because I can accidentally redefine the user object, like below.
const wait = (duration: number) => {
...
};
const getUser = async (id: number) => {
...
};
let user;
try {
user = await getUser(1);
// ... (a lot of code)
} catch (error) {
console.log("There was an error");
}
user = 1 // ← ❌ It might lead to a bug.
Solution
It's much simpler and more readable, don't you think?
Furthermore, the user variable is immutable and won't lead to unexpected errors.
const wait = (duration: number) => {
...
};
const getUser = async (id: number) => {
...
};
const catchError = async <T>(promise: Promise<T>): Promise<[undefined, T] | [Error]> => {
return promise
.then((data) => {
return [undefined, data] as [undefined, T];
})
.catch((error) => {
return [error];
});
};
const [error, user] = await catchError(getUser(1));
if (error) {
console.log(error);
}
console.log(user);
Please take a look at the video, which we have referenced. He explains it very carefully.
I have never actually used this pattern in actual work.I just wanted to hear your opinion on how practical it is.Because it was discussed in his Yotube comments and I wanted to know the answer. I’ll be exploring best practices based on the comments.👍
Happy Coding☀️