Skip to content

Instantly share code, notes, and snippets.

@lubieowoce
Last active March 15, 2024 12:56
Show Gist options
  • Save lubieowoce/a9b7c9f9f2c4084712bb3214fb52ebd9 to your computer and use it in GitHub Desktop.
Save lubieowoce/a9b7c9f9f2c4084712bb3214fb52ebd9 to your computer and use it in GitHub Desktop.
export type Thenable<T> = PendingThenable<T> | FulfilledThenable<T> | RejectedThenable<T>
export type PendingThenable<T> = Promise<T> & { status: 'pending' }
export type FulfilledThenable<T> = Promise<T> & { status: 'fulfilled', value: T }
export type RejectedThenable<T> = Promise<T> & { status: 'rejected', reason: unknown }
export function trackThenableState<T>(promise: Promise<T>): Thenable<T> {
const thenable = promise as Thenable<T>;
if ("status" in thenable && typeof thenable.status === "string") {
return thenable;
}
thenable.status = "pending";
thenable.then(
(value) => {
const fulfilledThenable = thenable as FulfilledThenable<T>;
fulfilledThenable.status = "fulfilled";
fulfilledThenable.value = value;
},
(error) => {
const rejectedThenable = thenable as RejectedThenable<T>;
rejectedThenable.status = "rejected";
rejectedThenable.reason = error;
}
);
return thenable;
}
/**
* @template T
* @typedef {PendingThenable<T> | FulfilledThenable<T> | RejectedThenable<T>} Thenable<T>
*/
/**
* @template T
* @typedef {Promise<T> & { status: 'pending' }} PendingThenable<T>
*/
/**
* @template T
* @typedef {Promise<T> & { status: 'fulfilled', value: T }} FulfilledThenable<T>
*/
/**
* @template T
* @typedef {Promise<T> & { status: 'rejected', reason: unknown }} RejectedThenable<T>
*/
/**
* @template T
* @returns {Thenable<T>}
*/
export function trackThenableState(/** @type {Promise<T>} */ promise) {
const thenable = /** @type {Thenable<T>} */ (promise);
if ('status' in thenable && typeof thenable.status === 'string') {
return thenable;
}
thenable.status = 'pending';
thenable.then(
(value) => {
const fulfilledThenable = /** @type {FulfilledThenable<T>} */ (thenable);
fulfilledThenable.status = 'fulfilled';
fulfilledThenable.value = value;
},
(error) => {
const rejectedThenable = /** @type {RejectedThenable<T>} */ (thenable);
rejectedThenable.status = 'rejected';
rejectedThenable.reason = error;
}
);
return thenable;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment