Skip to content

Instantly share code, notes, and snippets.

@leontastic
Last active November 21, 2023 00:30
Show Gist options
  • Save leontastic/68a856f1b6c40c7a3d19c971bcae1127 to your computer and use it in GitHub Desktop.
Save leontastic/68a856f1b6c40c7a3d19c971bcae1127 to your computer and use it in GitHub Desktop.
TS promise utils
export type PromiseFromProps<PromiseMap> = Promise<
{
[Property in keyof PromiseMap]: Awaited<PromiseMap[Property]>;
}
>;
export const fromProps = async <T>(object: T): PromiseFromProps<T> => {
// invert the object so that we get an array of promises resolving to key-value entries
const promises = Object.entries(object).map(([property, promise]) =>
Promise.resolve(promise).then((result) => [property, result]),
);
// get the promises out of the object
const results = await Promise.all(promises);
return Object.fromEntries(results);
};
import { fromProps } from './promise';
describe('fromProps', () => {
it('should return a promise resolving to the input object with promise properties already resolved', async () => {
const result = await fromProps({
a: Promise.resolve('bar'),
b: Promise.resolve('baz'),
c: Promise.resolve('foo'),
});
expect(result.a).toBe('bar');
expect(result.b).toBe('baz');
expect(result.c).toBe('foo');
});
it('should gracefully support non-promise properties', async () => {
const result = await fromProps({
a: 'bar',
b: 'baz',
c: 'foo',
});
expect(result.a).toBe('bar');
expect(result.b).toBe('baz');
expect(result.c).toBe('foo');
});
it('should reject with the first error encountered', async () => {
let rejectPromise: (rejectValue: any) => void;
const errorPromise = new Promise((_, reject) => {
rejectPromise = reject;
});
fromProps({
a: Promise.resolve('bar'),
b: Promise.resolve('baz'),
c: errorPromise,
})
.then(() => {
throw new Error('should not resolve if inner promises reject');
})
.catch((error) => {
expect(error.message).toBe('rejected!');
});
setTimeout(() => rejectPromise(new Error('rejected!')), 0);
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment