thames-technology / monads

Option, Result, and Either types for TypeScript - Inspired by Rust 🦀
https://thames-technology.github.io/monads/
MIT License
843 stars 32 forks source link

handling async results #75

Open paduc opened 4 years ago

paduc commented 4 years ago

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

slavovojacek commented 4 years ago

It requires work but let me look into it!

dmitrykologrivko commented 4 years ago

It is also actual for my case. It will be better to have the possibility to handle the async methods with chained construction. Thanks

paduc commented 4 years ago

You can see how superthrow implements it in their ResultAsync type.

slavovojacek commented 4 years ago

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! :)

paduc commented 4 years ago

@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...