This chapter follows Destructuring and spread.
Runtime errors versus static checks
TypeScript and other transpilers report compile-time issues before JavaScript runs. Plain JavaScript is parsed and executed just in time: invalid syntax throws SyntaxError at parse time; bad operations at runtime throw typed Error subclasses. There is no separate “checked exception” mechanism— callers choose whether to catch or let errors propagate to the host.
Common built-in types:
| Type | Typical trigger |
|---|---|
| SyntaxError | Invalid source (if {) |
| ReferenceError | Use of an undeclared binding |
| TypeError | Wrong type for the operation (e.g. undefined() ) |
| RangeError | Numeric or repeat count out of range |
| URIError | Bad encodeURI / decodeURI usage |
| AggregateError | Several failures bundled (e.g. Promise.any) |
try, catch, and finally
try runs a block. catch receives the thrown value (usually an Error instance). finally runs on both success and failure—use it for cleanup that must run regardless of return or throw.
try { risky();} catch (err) { console.error(`${err.name}: ${err.message}`);} finally { cleanup();}Creating an Error without throw does not stop execution—only throw begins unwinding.
try { throw new Error("Whoops!");} catch (e) { console.error(e.message);}The Error object and cause
Error instances expose message, name, and (in most engines) stack. ES2022 added cause in the options object to chain errors when rethrowing or wrapping.
try { parsePayload(raw);} catch (err) { throw new Error("Invalid payload", { cause: err });}
try { load();} catch (wrapped) { console.log(wrapped.cause); // original parse error}cause is intended for logging and inspection; console output may not expand it automatically.
Throwing your own errors
Use throw new TypeError(...) (or another built-in type) when the failure matches a standard category. Include a clear message; attach cause when translating low-level failures.
if (Number.isNaN(month)) { throw new TypeError("Month should be a number", { cause: { month } });}Custom Error subclasses
Extend Error for domain-specific failures. Set this.name, call super(message, options), and on V8 use Error.captureStackTrace(this, Constructor) so stacks point at your throw site.
class ValidationError extends Error { constructor(field, message, options) { super(message, options); this.name = "ValidationError"; this.field = field; if (Error.captureStackTrace) { Error.captureStackTrace(this, ValidationError); } }}
try { throw new ValidationError("email", "Invalid format");} catch (e) { if (e instanceof ValidationError) { console.error(e.field, e.message); } else { throw e; }}Prefer instanceof (or err.name when crossing realms) over comparing message strings.
Rethrowing with cause
Catch, add context, and rethrow so upper layers see one message while cause preserves the original for logs or retries.
function doWork() { try { doFailSomeWay(); } catch (err) { throw new Error("Failed in some way", { cause: err }); }}
try { doWork();} catch (err) { handleFailSomeWay(err.cause);}Re-throw unchanged errors you do not handle (throw e in a catch) so global handlers still run.
AggregateError
AggregateError groups multiple errors—Promise.any rejects with it when every input promise fails; each reason appears in errors.
const failures = [new Error("a"), new Error("b")];const agg = new AggregateError(failures, "All rejected");console.log(agg.errors.length); // 2Use it when your API performs parallel work and must report every failure, not only the first.
Async errors
Promises reject with whatever you pass to reject or throw inside an async executor. async/await maps rejections to catch on the awaited promise or to try/catch around await.
async function run() { try { await fetchBroken(); } catch (err) { console.log("Caught", err.message); }}
fetchBroken().catch((err) => console.log("Caught", err.message));Unhandled promise rejections behave like uncaught exceptions in Node and browsers—register process or window handlers in servers and apps.
This is the last chapter in Language Basics. Earlier material lives under JavaScript syntax at a glance.