I want to return errors in Javascript, and not throw them. This is the pure functional way. However, Javascript is not a pure functional programming language. Even if I anticipate some errors, run-time errors might creep in. Take this example.
let person = args = ({ name: args.name })Now, when I want to create a new person, I simply do:
person({ name: 'Gemma' }):
// > {name: "Gemma"}Excellent. But there's one problem. What if I don't pass in an object. What if I do this:
person();Oh no! I get an error that now breaks my app! It doesn't return anything either.
Partial application is one way to pre-load a function. But what we want is to preload a function that can try-catch any errors we have when I try to create a person.
let tryCatch = fn => args => {
try {
return fn(args);
} catch (e) {
return new Error(e)
}
}- This function takes a first argument, which it expects to be a function:
tryCatch(person);- This then returns another function.
// > args => {
// > try {
// > return fn(args);
// > } catch (e) {
// > return new Error(e)
// > }
// > }- So we have to call that returned function, but this time with our arguments:
tryCatch(person)({ name: 'Gemma' })Thankfully it returns with our new person. However, what if though we don't provide any arguments. Surely this breaks our app?
tryCatch(person)()Nope! It returns our error object instead of throwing an Uncaught TypeError
Error: TypeError: Cannot read property 'name' of undefined
at tryCatch (<anonymous>:9:12)
at <anonymous>:13:1
export const TryCatch = fn => args => {
try {
return Either.Right(fn(args));
} catch (e) {
return Either.Left(new Error(e));
}
}I know it's tied, but I don't need so much decoupling
let person = args = ({ name: args.name })
let setPerson = TryCatch(person);
setPerson({ name: 'Gemma' })
.fold(val => val, err => err);