fix: align RpcPromise construction with result elision - #251
Merged
Conversation
🦋 Changeset detectedLatest commit: 69de617 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
This comment was marked as low quality.
This comment was marked as low quality.
This comment was marked as low quality.
This comment was marked as low quality.
commit: |
ndisidore
force-pushed
the
feat/result-stub-elision
branch
3 times, most recently
from
August 19, 2026 21:14
05c32ea to
3bd5a25
Compare
ndisidore
marked this pull request as ready for review
August 19, 2026 22:39
ndisidore
marked this pull request as draft
August 19, 2026 22:50
Apply ElideStub -- the same transformation Result applies to a declared stub return -- to the RpcPromise constructor signature, so constructing from a promised stub produces exactly the type a method returning that stub would. The parameter accepts Promise<PayloadOrStub<T>>: the payload itself or, for stubable payloads, a stub of it. NoInfer keeps the stub arm out of inference, so an inferred T is always the promise's own resolution type; stubs of non-stubable payloads are rejected because ElideStub wouldn't elide them. Type tests pin constructor/method equivalence for bare, callable, plain-interface, and union payloads. (Extracted from the pre-squash feat/result-stub-elision branch: the constructor-alignment portion of its history that PR #253 didn't include.)
…tructor
new RpcPromise(Promise.resolve({ x: 1, f() { return 1 } })) failed to
type-check: a literal with a method is context-sensitive, and the stub
arm of the constructor's Promise<PayloadOrStub<T>> parameter poisons
the contextual type, collapsing Promise.resolve's inference to never.
The same value predeclared in a const, or with an explicit type
argument, worked fine.
The constructor type is now an overload pair. The first overload takes
a plain Promise<T> -- no stub arm in the contextual type -- which is
the one context-sensitive arguments are typed against. Since
PayloadOrStub's stub arm is NoInfer anyway, both overloads infer
identically; the second (the previous signature) matters only when T
is explicitly annotated and the payload is a stub.
Type tests cover the inline literal, the predeclared equivalent,
explicit-type-argument-with-stub-payload, and a promise for a
target-or-stub union.
ndisidore
force-pushed
the
feat/result-stub-elision
branch
from
August 20, 2026 14:22
bb7c807 to
f7d093e
Compare
…geset - Drop the explicit-type-argument equivalence case from stub-elision (rpc-base-cases pins the same overload with a strict expectType) and the consumeMaybe(constructedMaybe) call already implied by the strict Equal against maybeViaMethod. - Add a changeset for the constructor typing change; changeset-bot was flagging the PR as bump-less.
ndisidore
marked this pull request as ready for review
August 20, 2026 14:44
dimitropoulos
approved these changes
Aug 20, 2026
A ValidatedStub payload elides in the constructor (branded targets) or keeps its stub type (plain interfaces) only because ValidatedStub structurally matches capnweb's StubBase, which ElideStub keys on -- capnweb-validate maintains its own copy of that shape. Pin both cases so drift in either package can't silently change the constructor's type.
Merged
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.
new RpcPromise(promise)now produces the same type as an RPC method returning the same thing.Before, the two could disagree, which caused real problems:
dup(), and constructor-made promises couldn't be mixed with ones returned by RPC methods.Promise.resolve({ value, next() {…} })didn't compile (less important probably but not an expensive rider)The fix: the constructor's return type goes through the same stub elision as method results, and its parameter accepts either the payload or a stub of it. This also resolves @kentonv's
| Stub<T>question on #242. Type tests pin that the constructor and method returns agree for every payload shape.