Created
July 16, 2025 12:09
-
-
Save jjhiggz/44909695b01b3fff0a16a9e841ad7c2d to your computer and use it in GitHub Desktop.
sync-promise
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type SyncPromiseState<T, E = unknown> = | |
| { status: 'ok'; value: T } | |
| { status: 'error'; error: E }; | |
class SyncPromise<T, E = unknown> { | |
private state: SyncPromiseState<T, E>; | |
private constructor(state: SyncPromiseState<T, E>) { | |
this.state = state; | |
} | |
static create<T>(fn: () => T): SyncPromise<T, unknown> { | |
try { | |
return new SyncPromise({ status: 'ok', value: fn() }); | |
} catch (err) { | |
return new SyncPromise({ status: 'error', error: err }); | |
} | |
} | |
then<U>(fn: (value: T) => U): SyncPromise<U, E> { | |
if (this.state.status === 'ok') { | |
try { | |
return new SyncPromise<U, E>({ status: 'ok', value: fn(this.state.value) }); | |
} catch (err) { | |
return new SyncPromise<U, E>({ status: 'error', error: err as E }); | |
} | |
} | |
return new SyncPromise<U, E>(this.state); | |
} | |
catch<F>(fn: (error: E) => F): SyncPromise<T | F, never> { | |
if (this.state.status === 'error') { | |
try { | |
return new SyncPromise<T | F, never>({ status: 'ok', value: fn(this.state.error) }); | |
} catch (err) { | |
return new SyncPromise<T | F, never>({ status: 'error', error: err }); | |
} | |
} | |
return new SyncPromise<T | F, never>(this.state as any); | |
} | |
finally(fn: () => void): this { | |
try { | |
fn(); | |
} catch (_) { | |
// ignore errors in finally | |
} | |
return this; | |
} | |
unwrap(): T { | |
if (this.state.status === 'ok') { | |
return this.state.value; | |
} | |
throw this.state.error; | |
} | |
} | |
function createSyncPromise<T>(fn: () => T): SyncPromise<T, unknown> { | |
return SyncPromise.create(fn); | |
} | |
const result = createSyncPromise(() => { | |
if (Math.random() > 0.5) throw new Error("Bad luck!"); | |
return 42; | |
}) | |
.then(x => x + 1) | |
.then(x => `Result is ${x}`) | |
.catch(err => `Handled error: ${err}`) | |
.finally(() => console.log("Done with chain")) | |
.unwrap(); | |
console.log(result); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment