Write robust programs instead.
Humans are known to panic. This is widely considered bad design.
function eat(f: string) {
if (f === '🌯') ...
else throw; // panic
}
Panic is not useful™️. What's useful is a thorough assessment of the circumstances. dontpanic
brings you blazingly steadfast abstractions that help you recover from failure and guide your code to success.
DontPanic(eat)('🌯').onSuccess(sleep).onFailure(getPizza); // 🍕 Don't panic
throw
panics your program and sends it into an unrecoverable state. Most failures should be recoverable.
throw new Error('Invalid input'); // 🚯 Crash risk
return Failed('Invalid input'); // 🛣 No crash risk
99.9% of the time there is no need to panic.
It's easy to be implicit when handling exceptions. For example, a throwable function does not show that in its type signature. What happens in the success and the failure case is often hidden beneath layers of cognition, which leads to more unhandled errors and bugs.
const parsed = JSON.parse(input); // ⚠️ May panic
DontPanic(JSON.parse)(input); // ✅ Does not panic
Be explicit.
Try/catch creates two additional execution scopes. If another failure needs to be distinguished inside those, you might need to restructure your code to favor this, or end in nesting hell. Syntax should drive you to execution flow that is easy to reason about.
try {
const parsed = JSON.parse(input);
try {
const validated = validateInput(parsed);
register(validated);
} catch (e) {
handleValidationError(e);
}
} catch (e) {
handleParsingError(e); // 🪹 Far away from home
}
DontPanic(JSON.parse)(input) // 🥞
.onFailure(handleParsingError)
.onSuccess(validateInput)
.onFailure(handleValidationError)
.onSuccess(register);
Flatten your error handling.
npm install dontpanic