fix: restore Result-inferring andThrough overload on Err#678
Open
chatman-media wants to merge 1 commit into
Open
fix: restore Result-inferring andThrough overload on Err#678chatman-media wants to merge 1 commit into
andThrough overload on Err#678chatman-media wants to merge 1 commit into
Conversation
The Err class declared andThrough with only the `andThrough<F>(f: (t: T) => Result<unknown, F>)` overload, while the IResult interface and the Ok class also declare the `andThrough<R extends Result<unknown, unknown>>` overload first. When andThrough is called on a value typed as the Result union (Ok<T, E> | Err<T, E>) — for example after a preceding .andThen() — TS resolves the call against the signatures common to both members. Because Err was missing the first overload, resolution fell through to `andThrough<F>(...)`, which infers F from only the first member of a union-returning callback and drops the remaining error types. Adding the missing overload to Err makes union receivers infer the full error union, matching the behavior already seen when calling andThrough directly on an Ok. Closes supermacro#663
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Closes #663.
andThroughreports a spurious type error (and drops error types) when it is chained after a method that widens the receiver to theResult<T, E>union — e.g. a preceding.andThen():Curiously, removing the
.andThen((s) => ok(s))line makes the error disappear and the type infers correctly asResult<{ title, description }, ErrorA | ErrorB>.Root cause
andThroughis declared with two overloads on theIResultinterface and on theOkclass:but the
Errclass only declared the second one:When
andThroughis called on a value typed as the unionOk<T, E> | Err<T, E>(which is whatResult<T, E>is, and what.andThen()produces), TypeScript resolves the call against the signatures common to both union members. BecauseErrwas missing the first overload, resolution fell through toandThrough<F>(...), which infersFfrom only the first member of a union-returning callback (ErrorA) and discards the rest — producing(t) => Result<unknown, ErrorA>and the resulting mismatch.Calling
andThroughdirectly on anOk(which has both overloads) already worked, which is why the error only appears once the chain has widened toResult.Fix
Add the missing
andThrough<R extends Result<unknown, unknown>>overload to theErrclass so it matchesOkand theIResultinterface. The runtime implementation is unchanged (Err.andThroughstill just returnserr(this.error)).Tests
Added a type-level regression test in
tests/typecheck-tests.tsunder theandThroughblock. It reproduces the issue's exact shape (a.andThen(...)followed by.andThrough(...)with a union-returning callback) and asserts the inferred type isResult<{ title, description }, ErrorA | ErrorB>. The test fails (TS2345) onmasterand passes with this change.npm test— 117 runtime tests pass, type tests passnpm run lint/npm run typecheck— clean