TypeScript Tutorial
TypeScript Exceptions
throw signals a failure. try and catch recover without scattering error codes through every call.
A failure that jumps to a handler
Some functions cannot do their job: divide by zero, a value outside the legal range, a missing setting. You can return a special code from every function on the path. Or you can throw an error and let acatch block higher up handle it.
TypeScript uses the same try, catch, and throw as JavaScript. This chapter throws new Error("..."). Catch it, then read e.message. C++ does this withruntime_error and e.what(). The control flow is the same idea.
throw new Error
throw stops the current function. The object you throw travels up the call stack until a matchingcatch takes it. If nothing catches it, the program stops and the editor shows the error in the output pane.
Example
function divide(a: number, b: number): number {
if (b === 0) {
throw new Error("divide by zero");
}
return a / b;
}
try {
console.log(divide(10, 2));
console.log(divide(10, 0));
} catch (e) {
if (e instanceof Error) {
console.log(e.message);
}
}The first call prints 5. The second throws. The catch printsdivide by zero. The program still finishes. Without try, that second call would abort the run.
Open this in /typescript/try with Try it in TypeScript. Change the second divisor to a non-zero number and the catch never runs.
try and catch
Put the risky work in try. Put recovery in catch. Execution enters the catch only if something was thrown. After the catch finishes, the file continues as normal.
Example
try {
throw new Error("disk full");
} catch (e) {
if (e instanceof Error) {
console.log("recovered: " + e.message);
}
}
console.log("still running");Output is two lines. The exception was not fatal. That is the difference from an uncaught error: you choose a message, a fallback value, or a clean stop.
instanceof Error
In TypeScript, a catch binding is unknown under strict (or you leave it unannotated and narrow it). Do not read .message until you know you have an Error.instanceof Error is the usual check. Anything else can be stringified if you must log it.
| Piece | Role |
|---|---|
| try | Code that might throw |
| throw new Error("...") | Build and send the failure |
| catch (e) | Handle it; e is unknown until you narrow |
| e instanceof Error | Safe to read e.message |
You can throw a string or a number. Do not. Stick to Error (or a class that extends it) so instanceof and stack traces stay useful.
Validate, then throw
A helper can throw when the caller passes a bad value. The caller wraps the call in try/catch instead of checking a magic return code after every line.
Example
function percent(n: number): number {
if (n < 0 || n > 100) {
throw new Error("percent out of range");
}
return n;
}
try {
console.log(percent(40));
console.log(percent(140));
} catch (e) {
if (e instanceof Error) {
console.log(e.message);
}
}40 prints. 140 does not reach return n. The catch prints the message fromthrow.
When not to throw
- Do not throw for expected, everyday cases such as “the user typed a letter.” Ask again, or return a boolean.
- Do not use exceptions as a second return value for success. They are for failures you cannot handle locally.
- Keep
tryblocks short so it is obvious which call can fail.
These examples compile at /typescript/try. Next: array methods — push,map, filter, and reduce.