Skip to content

Commit 5df9122

Browse files
authored
EReturn type (#2659)
incidental ## Description Migrated from Agoric/agoric-sdk#9011 Define an `EReturn` type for the `Awaited<ReturnType<` pattern. ### Security Considerations none ### Scaling Considerations none ### Documentation Considerations This will appear in TSdoc ### Testing Considerations has tests ### Compatibility Considerations none ### Upgrade Considerations none
2 parents 2460645 + 43e4d43 commit 5df9122

File tree

8 files changed

+48
-35
lines changed

8 files changed

+48
-35
lines changed

packages/compartment-mapper/src/map-parser.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818
* SyncModuleTransform,
1919
* SyncModuleTransforms
2020
* } from './types.js';
21+
* @import {
22+
* EReturn
23+
* } from '@endo/eventual-send';
2124
*/
2225

2326
import { syncTrampoline, asyncTrampoline } from '@endo/trampoline';
@@ -82,7 +85,7 @@ const makeExtensionParser = (
8285
* @param {string} location
8386
* @param {string} packageLocation
8487
* @param {*} options
85-
* @returns {Generator<ReturnType<ModuleTransform>|ReturnType<SyncModuleTransform>, ParseResult, Awaited<ReturnType<ModuleTransform>|ReturnType<SyncModuleTransform>>>}
88+
* @returns {Generator<ReturnType<ModuleTransform>|ReturnType<SyncModuleTransform>, ParseResult, EReturn<ModuleTransform|SyncModuleTransform>>}
8689
*/
8790
function* getParserGenerator(
8891
bytes,

packages/daemon/test/endo.test.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ import { makeCryptoPowers } from '../src/daemon-node-powers.js';
2828
import { formatId } from '../src/formula-identifier.js';
2929
import { idFromLocator, parseLocator } from '../src/locator.js';
3030

31+
/**
32+
* @import {EReturn} from '@endo/eventual-send';
33+
*/
34+
3135
const cryptoPowers = makeCryptoPowers(crypto);
3236

3337
const { raw } = String;
@@ -227,7 +231,7 @@ test.beforeEach(t => {
227231

228232
test.afterEach.always(async t => {
229233
await Promise.allSettled(
230-
/** @type {Awaited<ReturnType<prepareConfig>>[]} */ (t.context).flatMap(
234+
/** @type {EReturn<typeof prepareConfig>[]} */ (t.context).flatMap(
231235
({ cancel, cancelled, config }) => {
232236
cancel(Error('teardown'));
233237
return [cancelled, stop(config)];

packages/eventual-send/src/E.js

+19-5
Original file line numberDiff line numberDiff line change
@@ -254,8 +254,11 @@ export default makeE;
254254
/** @typedef {ReturnType<makeE>} EProxy */
255255

256256
/**
257-
* Creates a type that accepts both near and marshalled references that were
258-
* returned from `Remotable` or `Far`, and also promises for such references.
257+
* Declare an object that is potentially a far reference of type Primary whose
258+
* auxilliary data has type Local. This should be used only for consumers of
259+
* Far objects in arguments and declarations; the only creators of Far objects
260+
* are distributed object creator components like the `Far` or `Remotable`
261+
* functions.
259262
*
260263
* @template Primary The type of the primary reference.
261264
* @template [Local=DataOnly<Primary>] The local properties of the object.
@@ -274,14 +277,24 @@ export default makeE;
274277
* @see {@link https://github.com/microsoft/TypeScript/issues/31394}
275278
* @template T
276279
* @typedef {PromiseLike<T> | T} ERef
280+
* Declare that `T` may or may not be a Promise. This should be used only for
281+
* consumers of arguments and declarations; return values should specifically be
282+
* `Promise<T>` or `T` itself.
283+
*/
284+
285+
/**
286+
* The awaited return type of a function.
287+
*
288+
* @template {(...args: any[]) => any} T
289+
* @typedef {T extends (...args: any[]) => infer R ? Awaited<R> : never} EReturn
277290
*/
278291

279292
/**
280293
* @template {import('./types.js').Callable} T
281294
* @typedef {(
282295
* ReturnType<T> extends PromiseLike<infer U> // if function returns a promise
283296
* ? T // return the function
284-
* : (...args: Parameters<T>) => Promise<Awaited<ReturnType<T>>> // make it return a promise
297+
* : (...args: Parameters<T>) => Promise<EReturn<T>> // make it return a promise
285298
* )} ECallable
286299
*/
287300

@@ -399,8 +412,9 @@ export default makeE;
399412
*/
400413

401414
/**
402-
* Type for an object that must only be invoked with E. It supports a given
403-
* interface but declares all the functions as asyncable.
415+
* Declare a near object that must only be invoked with E, even locally. It
416+
* supports the `T` interface but additionally permits `T`'s methods to return
417+
* `PromiseLike`s even if `T` declares them as only synchronous.
404418
*
405419
* @template T
406420
* @typedef {(

packages/eventual-send/src/exports.d.ts

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export type {
1212
ERef,
1313
EProxy,
1414
EOnly,
15+
EReturn,
1516
RemoteFunctions,
1617
LocalRecord,
1718
FilteredKeys,

packages/eventual-send/src/exports.test-d.ts

+14-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/* eslint-disable @endo/no-polymorphic-call, import/no-extraneous-dependencies, no-restricted-globals */
22
import { expectType } from 'tsd';
33
import { E } from '../test/_get-hp.js';
4-
import type { ERef, FarRef } from './exports.js';
4+
import type { ERef, EReturn, FarRef } from './exports.js';
55

66
// Check the legacy ERef type
77
const foo = async (a: ERef<{ bar(): string; baz: number }>) => {
@@ -21,6 +21,19 @@ const foo = async (a: ERef<{ bar(): string; baz: number }>) => {
2121
a.bar();
2222
};
2323

24+
// EReturn
25+
{
26+
const makeFoo = async () => 'foo' as const;
27+
expectType<Promise<'foo'>>(makeFoo());
28+
type Foo = EReturn<typeof makeFoo>;
29+
expectType<Foo>('foo');
30+
31+
const fooP = Promise.resolve('foo' as const);
32+
expectType<Promise<'foo'>>(fooP);
33+
// @ts-expect-error takes only functions
34+
EReturn<typeof fooP>;
35+
}
36+
2437
// FarRef<T>
2538
const foo2 = async (a: FarRef<{ bar(): string; baz: number }>) => {
2639
const { baz } = await a;

packages/far/src/exports.d.ts

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { FarRef, ERef, EOnly, EReturn } from '@endo/eventual-send';

packages/far/src/exports.js

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// Just a dummy to use exports.d.ts and satisfy runtime imports.
2+
export {};

packages/far/src/index.js

+2-27
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,5 @@
11
export { E } from '@endo/eventual-send';
22
export { Far, getInterfaceOf, passStyleOf } from '@endo/pass-style';
33

4-
// TODO re-export from eventual-send, may require .d.ts
5-
/**
6-
* @template Primary
7-
* @template [Local=import('@endo/eventual-send').DataOnly<Primary>]
8-
* @typedef {import('@endo/eventual-send').FarRef<Primary, Local>} FarRef
9-
* Declare an object that is potentially a far reference of type Primary whose
10-
* auxilliary data has type Local. This should be used only for consumers of
11-
* Far objects in arguments and declarations; the only creators of Far objects
12-
* are distributed object creator components like the `Far` or `Remotable`
13-
* functions.
14-
*/
15-
16-
/**
17-
* @template T
18-
* @typedef {import('@endo/eventual-send').ERef<T>} ERef
19-
* Declare that `T` may or may not be a Promise. This should be used only for
20-
* consumers of arguments and declarations; return values should specifically be
21-
* `Promise<T>` or `T` itself.
22-
*/
23-
24-
/**
25-
* @template T
26-
* @typedef {import('@endo/eventual-send').EOnly<T>} EOnly
27-
* Declare a near object that must only be invoked with E, even locally. It
28-
* supports the `T` interface but additionally permits `T`'s methods to return
29-
* `PromiseLike`s even if `T` declares them as only synchronous.
30-
*/
4+
// eslint-disable-next-line import/export
5+
export * from './exports.js';

0 commit comments

Comments
 (0)