Let's say I am writing a simple library in JavaScript, with only a few functions:
- Calculate the factorial of a positive natural number
- Find the least common multiple from an array of integers
- And so on...
In each of these functions, I will check if the given parameter is acceptable before performing any operations, and would like to raise an error if it is not. (Raising errors is a good programming practice, right?)
To do this, I can think of a few different options. Take the factorial(x)
function, for example:
Option 1: simply
throw new Error("Invalid argument for factorial(): natural number expected.")
Option 2: define a
class NotANaturalNumberError extends Error {}
in the global scope (!) and thenthrow new NotANaturalNumberError("Invalid argument for factorial(): natural number expected.")
Option 3: almost the same as option 2 but not cluttering the global scope, and instead defining
class NotANaturalNumberError extends Error {}
in a local scope (such as inside a closure)
They all have pros and cons, though:
Option 1:
- Cons: tricky code would be necessary to tell it apart from other possible errors, since it is just an
Error
, the superclass. - Pros: one simple line of code, does not clutter the global scope
- Cons: tricky code would be necessary to tell it apart from other possible errors, since it is just an
Option 2:
- Cons: clutters the global scope, which is generally considered terrible, and might conflict with something else. Also, the user must somehow be informed that it's called
NotANaturalNumberError
. - Pros: the user of the library can do the check
e instanceof NotANaturalNumberError
when catching an error
- Cons: clutters the global scope, which is generally considered terrible, and might conflict with something else. Also, the user must somehow be informed that it's called
Option 3:
- Cons: the user of the library can't do the check
e instanceof NotANaturalNumberError
when catching an error sinceNotANaturalNumberError
is not defined externally. - Pros: does not clutter the global scope
- Cons: the user of the library can't do the check
None of these options seem good enough, and I couldn't think of any other. What is the proper way to do this? How the big libraries out there do this?