From 98c5b62c3c99808894649194e8058f0e395807d6 Mon Sep 17 00:00:00 2001 From: Turadg Aleahmad Date: Fri, 10 Feb 2023 09:13:28 -0800 Subject: [PATCH 1/2] chore(types): allValues support heterogenous mapping --- packages/inter-protocol/src/collect.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/inter-protocol/src/collect.js b/packages/inter-protocol/src/collect.js index 5408fb2242a..c05c4dc780f 100644 --- a/packages/inter-protocol/src/collect.js +++ b/packages/inter-protocol/src/collect.js @@ -3,7 +3,7 @@ const { fromEntries, keys, values } = Object; /** @type { (xs: X[], ys: Y[]) => [X, Y][]} */ export const zip = (xs, ys) => harden(xs.map((x, i) => [x, ys[+i]])); -/** @type { (obj: Record>) => Promise> } */ +/** @type { >>(obj: T) => Promise<{ [K in keyof T]: Awaited}> } */ export const allValues = async obj => { const resolved = await Promise.all(values(obj)); // @ts-expect-error cast From 2683f478eb1bb956ad3d2af7dca16e6a64ee0006 Mon Sep 17 00:00:00 2001 From: Turadg Aleahmad Date: Fri, 10 Feb 2023 09:07:11 -0800 Subject: [PATCH 2/2] chore(types): improve deeplyFulfilledObject return type --- packages/internal/src/utils.js | 19 +++++++++++++------ packages/internal/test/test-utils.js | 20 ++++++++++++++++++++ 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/packages/internal/src/utils.js b/packages/internal/src/utils.js index abd8d23e8ef..267e04f840c 100644 --- a/packages/internal/src/utils.js +++ b/packages/internal/src/utils.js @@ -248,18 +248,25 @@ export const bindAllMethods = obj => ); harden(bindAllMethods); +/** + * @template T + * @typedef {{[KeyType in keyof T]: T[KeyType]} & {}} Simplify + * flatten the type output to improve type hints shown in editors + * https://github.com/sindresorhus/type-fest/blob/main/source/simplify.d.ts + */ + +/** + * @typedef {(...args: any[]) => any} Callable + */ + /** * @template {{}} T - * @typedef {{ [K in keyof T]: DeeplyAwaited }} DeeplyAwaitedObject + * @typedef {{ [K in keyof T]: T[K] extends Callable ? T[K] : DeeplyAwaited }} DeeplyAwaitedObject */ /** - * Caveats: - * - doesn't recur within Promise results - * - resulting type has wrapper in its name - * * @template T - * @typedef {T extends PromiseLike ? Awaited : T extends {} ? DeeplyAwaitedObject : Awaited} DeeplyAwaited + * @typedef {T extends PromiseLike ? Awaited : T extends {} ? Simplify> : Awaited} DeeplyAwaited */ /** diff --git a/packages/internal/test/test-utils.js b/packages/internal/test/test-utils.js index 72167721e87..1a047079031 100644 --- a/packages/internal/test/test-utils.js +++ b/packages/internal/test/test-utils.js @@ -2,6 +2,7 @@ import test from 'ava'; import '@endo/init'; +import { Far } from '@endo/marshal'; import { fromUniqueEntries, objectMap, @@ -10,6 +11,7 @@ import { whileTrue, untilTrue, forever, + deeplyFulfilledObject, } from '../src/utils.js'; test('fromUniqueEntries', t => { @@ -57,6 +59,24 @@ test('objectMap', t => { ); }); +test('deeplyFulfilledObject', async t => { + const someFar = Far('somefar', { getAsync: () => Promise.resolve('async') }); + const unfulfilled = harden({ + obj1: { + obj2a: { + stringP: Promise.resolve('foo'), + }, + obj2b: someFar, + }, + }); + const fulfilled = await deeplyFulfilledObject(unfulfilled); + // JS check that it's a now string + fulfilled.obj1.obj2a.stringP.length; + t.deepEqual(fulfilled, { + obj1: { obj2a: { stringP: 'foo' }, obj2b: someFar }, + }); +}); + test('makeMeasureSeconds', async t => { const times = [1000.25, 2000.75, NaN]; /** @type {() => number} */