Skip to content

Commit

Permalink
types: GuestInterface supports synchronous returns
Browse files Browse the repository at this point in the history
  • Loading branch information
0xpatrickdev committed Sep 10, 2024
1 parent b36bb55 commit 0ac0e68
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 9 deletions.
8 changes: 5 additions & 3 deletions packages/async-flow/src/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,11 @@ export type GuestInterface<T> = {
? (...args: Parameters<T[K]>) => Promise<R>
: T[K] extends HostAsyncFuncWrapper
? GuestOf<T[K]>
: T[K] extends object
? GuestInterface<T[K]>
: T[K];
: T[K] extends (...args: any[]) => infer R
? T[K]
: T[K] extends object
? GuestInterface<T[K]>
: T[K];
};

/**
Expand Down
61 changes: 56 additions & 5 deletions packages/async-flow/test/types.test-d.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,73 @@
import { expectType } from 'tsd';
import type { Zone } from '@agoric/base-zone';
import type { Vow, VowTools } from '@agoric/vow';
import type { HostOf, GuestOf } from '../src/types.js';
import type {
HostOf,
GuestOf,
HostInterface,
GuestInterface,
} from '../src/types.js';

const castable: unknown = null;
const vt: VowTools = null as any;

const sumVow = (a: number, b: number) => vt.asVow(() => a + b);

const sumPromise = (a: number, b: number) => Promise.resolve(a + b);

expectType<(p1: number, p2: number) => Promise<number>>(
null as unknown as GuestOf<typeof sumVow>,
castable as GuestOf<typeof sumVow>,
);

expectType<(p1: number, p2: number) => Vow<number>>(
null as unknown as HostOf<typeof sumPromise>,
castable as HostOf<typeof sumPromise>,
);
expectType<(p1: number, p2: number) => Vow<void>>(
// @ts-expect-error incompatible return type
null as unknown as HostOf<typeof sumPromise>,
castable as HostOf<typeof sumPromise>,
);

// Test HostInterface and GuestInterface with an exoClass object
type ExoAPIBase = {
getValue: () => number;
setValue: (value: number) => void;
getCopyData: () => Record<string, number>[];
// TODO include `getRemote() => Guarded<...>`, since durable exos are passable
};
type ExoGuestAPI = ExoAPIBase & {
getValueAsync: () => Promise<number>;
};

type ExoHostAPI = ExoAPIBase & {
getValueAsync: () => Vow<number>;
};

expectType<
ExoAPIBase & {
getValueAsync: () => Vow<number>;
}
>(castable as HostInterface<ExoGuestAPI>);
expectType<
ExoAPIBase & {
getValueAsync: () => Promise<number>;
}
>(castable as GuestInterface<ExoHostAPI>);

// Test HostInterface and GuestInterface with classKit (nested) objects
expectType<{
facet: ExoAPIBase & {
getValueAsync: () => Vow<number>;
};
}>(
castable as HostInterface<{
facet: ExoGuestAPI;
}>,
);
expectType<{
facet: ExoAPIBase & {
getValueAsync: () => Promise<number>;
};
}>(
castable as GuestInterface<{
facet: ExoHostAPI;
}>,
);
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ export const depositAndDelegate = async (
const { give } = seat.getProposal();
await zoeTools.localTransfer(seat, contractState.localAccount, give);

// @ts-expect-error Type 'GuestInterface<() => HostInterface<ChainAddress>>' has no call signatures.
const address = account.getAddress();
try {
await contractState.localAccount.transfer(give.Stake, address);
Expand Down

0 comments on commit 0ac0e68

Please sign in to comment.