Exceptions

Why Define Custom Errors?

Defining Exceptions makes throwing errors more streamlined and allows for inference in upstream catch blocks. Although you are free to throw a regular Error wherever you like, we recommend defining any error used more than once, or that you many need to reason about.

Composing Exceptions

Defining a new Exception is easy, and can handle any number of arbitrary constructor parameters.
1
import { Exception, ExceptionContract } from "@masqueradejs/backstage"
2
3
export class MissingDomvalueError extends Exception implements ExceptionContract {
4
constructor(public readonly tag: string, public readonly fooBar?: boolean) {
5
super(
6
`The page could not locate the ${tag} element.`
7
)
8
}
9
}
10
Copied!

Streamlined Throws

Throwing an error becomes much more efficient and keeps your error text DRY.
1
import { MissingDomValueError } from "../exceptions"
2
3
// ...
4
5
// Attempt to scrape the first h1 tag from a page.
6
const headingText = await page.$("h1")
7
8
// If the page did contain the expected heading text value, throw a typed error.
9
if(!headingText) {
10
throw new MissingDomValueError("h1")
11
}
12
13
// We can continue knowing headingText is valiud.
14
console.log(`Found heading text ${headingText}`)
Copied!

Enhanced Catches

With typed errors we are able to infer the type and additional context about the error prior to handling.
1
// Resolve a new Puppeteer page.
2
const page: Page = await browser.newPage()
3
4
try {
5
// Attempt to scrape the heading text.
6
const headingText: string = await myHeadingScraperLogic.run(page)
7
} catch (err) {
8
// Handle errors.
9
if(err instanceof MissingDomValueError && MissingDomValueError.tag === "h1") {
10
// Handle specific missing heading text, knowing that it was for a missing h1 tag.
11
} else {
12
// Handle as a regular error.
13
}
14
}
Copied!