Open Alexander-Prime opened 1 year ago
Hi,
I'm incredibly busy at the moment and sadly working on improvements has ended up on the back burner.
In this case, the issue you raise exists because in Rust you wouldn't be able to have a string | number
type. The type signatures for the core functions are copied from Rust.
I am reluctant to change them - this library promises Rust's Option and Result types. There are other Result and FP libraries which may serve you better if this is what you need.
Always keen to hear other opinions though.
Yeah, I realized not long after submitting this that it may have been a deliberate choice.
For what it's worth, I still think this would be a win for ergonomics. The extra plumbing to make fail().andThen(failDifferently)
work is a bit noisy:
// Either this, with a union like `SomeError | OtherError`
(fail() as Result<Something, MyErrorUnion>)
.andThen(failDifferently);
// Or this, mimicking Rust's pattern of varying error types via enum
fail()
.mapErr(wrapError)
.andThen(x => failDifferently(x).mapErr(wrapError));
But frankly, neither of these is a showstopper for me, and there's probably better patterns I'm missing.
If other opinions sway you and you decide to support this after all, I'm happy to open a PR some weekend or another. Otherwise I don't mind closing this.
I was thinking about this today. I think I'm decided that I'm not going to expand the type signatures at this time, but maybe this pattern helps:
class MyError extends Error {}
class MyOtherError extends Error {}
function fail(): Result<number, Error> {}
function failDifferent(): Result<number, MyError> {}
function failOther(): Result<number, MyOtherError> {}
fail().andThen(failDifferent).andThen(failOther);
Now, I grant that you don't retain complete type information on the possible error types.... even if you had that, you'd still have to check the error type if you wanted to perform different actions depending on the error.
Bumped into this issue too. I think it makes sense that oxide sticks to the Rust type. I made another one @wopjs/tsur that is more TypeScript flavored as complement.
The
Option
- andResult
-chaining methods (and
,andThen
,or
, andorElse
) don't allow the type params that they aren't mapping to differ from the type ofthis
. That is,Result<T, E>.andThen
takes (usually infers) a type parameter that will replaceT
, but there isn't a way to add a new error type toE
. This makes it difficult to chainResult
s unless they all fail with the lowest common denominator (usually a basicError
).For a realistic example, if I want to fetch some resource and then parse it with Zod, TS complains about my error types being mismatched:
The same problem exists the other way around for
or
andorElse
. If I saySome("a").or(Some(1))
, instead of theOption<string | number>
I expect, I get a TS error that boils down toType 'string' is not assignable to type 'number'.
This should be fixable with a second type param on these method signatures: