Originally, NeverThrow/Ok
and NeverThrow/Err
were @psalm-immutable
to allow usage of @template-covariant
on them. It turned out that @psalm-immutable
was too strict: all properties must be readonly which is good, but all methods must be mutation-free, which in this specific case is bad.
Ok|Err
methods will cause side-effects most of the time, they are meant to cause side-effects: Database queries can fail, HTTP calls can fail, etc. Pure functions cannot really fail, at least not in the same way. Forcing all calls to andThen()
, orElse()
or match()
to be mutation-free was a bad idea, so we decided to remove the immutable constraint on Ok|Err
(we did keep the inner properties read-only). As a result, we cannot have @template-covariant
which means the types don't "collapse" to Ok<A | B>
but stay Ok<A> | Ok<B>
. We can live with that.
map()
and mapErr()
were kept mutation-free, but it turns out it's just as painful and hard to use. We should also relax the constraint on those methods too.