From 103635f695d8f8df975b387bf9a84df10274cb22 Mon Sep 17 00:00:00 2001 From: Turadg Aleahmad Date: Thu, 23 Jun 2022 07:03:31 -0700 Subject: [PATCH 1/2] fix: typedef of E() proxy parameter constraint --- packages/eventual-send/src/index.d.ts | 4 ++-- packages/eventual-send/src/index.test-d.ts | 27 ++++++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/packages/eventual-send/src/index.d.ts b/packages/eventual-send/src/index.d.ts index 0b3064e267..997dd9ec91 100644 --- a/packages/eventual-send/src/index.d.ts +++ b/packages/eventual-send/src/index.d.ts @@ -234,7 +234,7 @@ interface EProxy { * @param x target for method/function call * @returns method/function call proxy */ - (x: T): ECallableOrMethods>; + (x: T): ECallableOrMethods>; /** * E.get(x) returns a proxy on which you can get arbitrary properties. @@ -245,7 +245,7 @@ interface EProxy { * @param x target for property get * @returns property get proxy */ - readonly get: (x: T) => EGetters>; + readonly get: (x: T) => EGetters>; /** * E.resolve(x) converts x to a handled promise. It is diff --git a/packages/eventual-send/src/index.test-d.ts b/packages/eventual-send/src/index.test-d.ts index 74aca3b523..a96fed2fe0 100644 --- a/packages/eventual-send/src/index.test-d.ts +++ b/packages/eventual-send/src/index.test-d.ts @@ -46,3 +46,30 @@ const foo2 = async (a: FarRef<{ bar(): string; baz: number }>) => { // @ts-expect-error - calling directly is valid but not yet in the typedef a.bar; }; + +// Nullish handling +type SomeRemotable = { someMethod: () => 'hello'; someVal: 'alsoHello' }; +const undefinedCase = () => { + let ref: SomeRemotable | undefined; + // @ts-expect-error could be undefined + E(ref).someMethod(); + // @ts-expect-error optional chaining doesn't work with E() + E(ref)?.someMethod(); + // @ts-expect-error could be undefined + E.get(ref); + const getters = E.get(ref!); + getters.someMethod.then(sayHello => sayHello()); + getters.someVal; +}; +const nullCase = () => { + let ref: SomeRemotable | null; + // @ts-expect-error could be null + E(ref).someMethod(); + // @ts-expect-error optional chaining doesn't work with E() + E(ref)?.someMethod(); + // @ts-expect-error could be null + E.get(ref); + const getters = E.get(ref!); + getters.someMethod.then(sayHello => sayHello()); + getters.someVal; +}; From c4f23d754d92883b5f470bc74a0b029e152e0e08 Mon Sep 17 00:00:00 2001 From: Turadg Aleahmad Date: Tue, 28 Jun 2022 09:58:29 -0700 Subject: [PATCH 2/2] WIP for matthieu to play with --- packages/eventual-send/src/index.d.ts | 7 +++++-- packages/eventual-send/src/index.test-d.ts | 20 +++++++++++++++++++- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/packages/eventual-send/src/index.d.ts b/packages/eventual-send/src/index.d.ts index 997dd9ec91..7c75759f6c 100644 --- a/packages/eventual-send/src/index.d.ts +++ b/packages/eventual-send/src/index.d.ts @@ -234,7 +234,10 @@ interface EProxy { * @param x target for method/function call * @returns method/function call proxy */ - (x: T): ECallableOrMethods>; + // (x: NonNullable): ECallableOrMethods>; + // (undefined): Record; + // (x: null): Record; + (x: NonNullable): ECallableOrMethods>; /** * E.get(x) returns a proxy on which you can get arbitrary properties. @@ -245,7 +248,7 @@ interface EProxy { * @param x target for property get * @returns property get proxy */ - readonly get: (x: T) => EGetters>; + readonly get: (x: T) => EGetters>; /** * E.resolve(x) converts x to a handled promise. It is diff --git a/packages/eventual-send/src/index.test-d.ts b/packages/eventual-send/src/index.test-d.ts index a96fed2fe0..84353f33b7 100644 --- a/packages/eventual-send/src/index.test-d.ts +++ b/packages/eventual-send/src/index.test-d.ts @@ -1,5 +1,6 @@ /* eslint-disable @endo/no-polymorphic-call, import/no-extraneous-dependencies, no-restricted-globals, prettier/prettier */ import { expectType } from 'tsd'; +import { Far } from '@endo/marshal'; import { E } from '../test/get-hp.js'; import { DataOnly, ERef } from './index.js'; @@ -51,13 +52,30 @@ const foo2 = async (a: FarRef<{ bar(): string; baz: number }>) => { type SomeRemotable = { someMethod: () => 'hello'; someVal: 'alsoHello' }; const undefinedCase = () => { let ref: SomeRemotable | undefined; + // @ts-expect-error can't proxy an undefined value + E(ref); // @ts-expect-error could be undefined E(ref).someMethod(); // @ts-expect-error optional chaining doesn't work with E() E(ref)?.someMethod(); // @ts-expect-error could be undefined E.get(ref); - const getters = E.get(ref!); + const getters = E.get(ref); + expectType < EGetters(getters); + getters.someMethod.then(sayHello => sayHello()); + getters.someVal; +}; +const promiseUndefinedCase = () => { + let ref: Promise; + // @ts-expect-error can't proxy an undefined value + E(ref); + // @ts-expect-error could be undefined + E(ref).someMethod(); + // @ts-expect-error optional chaining doesn't work with E() + E(ref)?.someMethod(); + // @ts-expect-error could be undefined + E.get(ref); + const getters = E.get(ref); getters.someMethod.then(sayHello => sayHello()); getters.someVal; };