monads
monads copied to clipboard
handling async results
Hi,
A lot of my methods return a Promise<Result<T,K>>
because they handle async behaviour (writing to the database for instance).
I would love to be able to chain these methods with and_then
but the latter only accepts methods that return a Result<T,K>
.
Example:
const user = makeUser({ name, email }).and_then(userDB.insert);
// where userDB.insert = (user) => Promise<Result<User, Error>>
Is this possible currently or does this require additional work ? I'm willing to help if I can.
Cheers
It requires work but let me look into it!
It is also actual for my case. It will be better to have the possibility to handle the async methods with chained construction. Thanks
You can see how superthrow
implements it in their ResultAsync type.
It's an interesting one, because in a way you could also just use Promise
as if it was a Result
. The only thing you're losing is the error type (e.g. Promise<T>
vs Result<T, E>
), but in the context of Promises the errors would ideally always be instanceof Error
.
What I am trying to say is that you could simply do...
const validateParams = async (params): Promise<UserAttributes> => {
...
}
const insertUser = async (attrs: UserAttributes): Promise<User> => {
const { id, firstName, lastName, insertedAt } = await db.insert(attrs)
return { id, firstName, lastName, insertedAt }
}
const user = validateParams(params).then(insertUser)
...which would be conceptually equivalent to Result<T, E>.andThen(...)
.
However, if there is a use-case where Result<T, E>
is absolutely necessary, please let me know! :)
@slavovojacek From my point of view, the only advantage of Result
is that errors are typed. If you don't care about the error type, you can do everything with plain vars and promises.
Also, with a ResultAsync
type, you can guarantee your caller that your method will never throw...