Created
June 17, 2025 13:09
-
-
Save cshaa/34cddad8e1747db4068b43ebb970bd50 to your computer and use it in GitHub Desktop.
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
class ResultClass<IsOk extends boolean, OkType, ErrType> { | |
constructor( | |
/** | |
* For `Ok(value)` returns `true`; for `Err(value)` returns `false`. | |
*/ | |
public readonly isOk: IsOk, | |
/** | |
* For `Ok(value)` returns `value`; for `Err(value)` returns `undefined`. | |
*/ | |
public readonly okInner: IsOk extends true ? OkType : undefined, | |
/** | |
* For `Ok(value)` returns `undefined`; for `Err(value)` returns `value`. | |
*/ | |
public readonly errInner: IsOk extends true ? undefined : ErrType | |
) {} | |
*[Symbol.iterator](): IterableIterator<OkType> { | |
if (this.isOk) yield this.okInner!; | |
} | |
get isErr(): IsOk extends true ? false : IsOk extends false ? true : boolean { | |
return !this.isOk as any; | |
} | |
isOkAnd(fn: (x: OkType) => boolean): boolean { | |
if (this.isOk) return fn(this.okInner!); | |
return false; | |
} | |
isErrAnd(fn: (e: ErrType) => boolean): boolean { | |
if (this.isErr) return fn(this.errInner!); | |
return false; | |
} | |
map<S>(fn: (value: OkType) => S): Result<S, ErrType> { | |
if (this.isOk) return Result.Ok(fn(this.okInner!)); | |
return self as any; | |
} | |
mapErr<E>(fn: (err: ErrType) => E): Result<OkType, E> { | |
if (this.isErr) return Result.Err(fn(this.errInner!)); | |
return self as any; | |
} | |
} | |
type Result<T, E> = Result.Ok<T> | Result.Err<E>; | |
namespace Result { | |
export type Ok<T> = ResultClass<true, T, never>; | |
export const Ok = <T>(value: T) => new ResultClass(true, value, undefined as never); | |
export type Err<E> = ResultClass<false, never, E>; | |
export const Err = <E>(err: E) => new ResultClass(false, undefined as never, err); | |
export function from<T>(fn: () => T): Result<T, any>; | |
export function from<T>(fn: Promise<T>): Promise<Result<T, any>>; | |
export function from<T>(fn: Promise<T> | (() => T)): Result<T, any> | Promise<Result<T, any>> { | |
if (typeof fn === 'function') { | |
try { | |
return Result.Ok(fn()); | |
} catch (e) { | |
return Result.Err(e); | |
} | |
} else { | |
return (async () => { | |
try { | |
return Result.Ok(await fn); | |
} catch (e) { | |
return Result.Err(e); | |
} | |
})(); | |
} | |
} | |
} | |
export { Result }; | |
export const isResult = (x: unknown): x is Result<unknown, unknown> => x instanceof ResultClass; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment