Last active
November 15, 2021 21:17
-
-
Save kurtbuilds/aa72f8ce9a2b07aa2f85fe520544f8ee 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
//Typescript version of Rust's Result type | |
interface IValue<T> { | |
type: 'value' | |
value: T | |
} | |
interface IError<E extends Error> { | |
type: 'error' | |
error: E | |
} | |
type ResultType<T, E extends Error> = IValue<T> | IError<E> | |
export class Result<T, E extends Error> { | |
constructor(public result: ResultType<T, E>) { } | |
static value<T>(value: T): Result<T, any> { | |
return new Result({ | |
type: 'value', | |
value, | |
}) | |
} | |
static error<E extends Error>(error: E): Result<any, E> { | |
return new Result({ | |
type: 'error', | |
error, | |
}) | |
} | |
unwrap(): T { | |
switch (this.result.type) { | |
case 'value': return this.result.value | |
case 'error': throw this.result.error | |
} | |
} | |
unwrap_err(): E { | |
switch (this.result.type) { | |
case 'error': return this.result.error | |
case 'value': throw new Error('Tried to unwrap_err on result, but not an error.') | |
} | |
} | |
map<S>(f: (value: T) => S): Result<S, E> { | |
switch (this.result.type) { | |
case 'value': | |
return new Result<S, E>({ | |
type: 'value', | |
value: f(this.result.value), | |
}) | |
case 'error': return new Result<S, E>(this.result) | |
} | |
} | |
async amap<S>(f: (value: T) => Promise<S>): Promise<Result<S, E>> { | |
switch (this.result.type) { | |
case 'value': | |
return new Result<S, E>({ | |
type: 'value', | |
value: (await f(this.result.value)), | |
}) | |
case 'error': | |
return new Result<S, E>(this.result) | |
} | |
} | |
unwrap_or(d: T): T { | |
switch (this.result.type) { | |
case 'value': return this.result.value | |
case 'error': return d | |
} | |
} | |
is_ok(): boolean { | |
return this.result.type === 'value' | |
} | |
is_err(): boolean { | |
return this.result.type === 'error' | |
} | |
} | |
export function Ok<T>(v: T): Result<T, any> { | |
return Result.value(v) | |
} | |
export function Err<E extends Error>(e: E): Result<any, E> { | |
return Result.error(e) | |
} | |
export function Maybe<T, E extends Error>(v: T | null | undefined): Result<T, Error> { | |
if (v === null || v === undefined) { | |
return Err(new Error('Not found.')) | |
} else { | |
return Ok(v!) | |
} | |
} | |
export function Serr(message: string): Result<any, Error> { | |
return Result.error(new Error(message)) | |
} | |
//Other Rust primitives, not directly related to Result | |
/** Can be used for exhaustive checks, ex: | |
let name: 'fetch-transactions' | 'query-email-receipts' | 'spending-summary' | 'transaction-review' | |
if (name === 'query-email-receipts') { | |
return handle_email_receipt_query_job; | |
} else if (name === 'fetch-transactions') { | |
return handle_fetch_transactions | |
} else if (name === 'spending-summary') { | |
return unimplemented() | |
} else if (name === 'transaction-review') { | |
return unimplemented() | |
} else { | |
// if any type possibility was unhandled, this would report a typecheck error at checktime. | |
// this happens because infallible gives its parameter the `never` type, meaning there can | |
// be no instance of an object of that type. | |
infallible(name) | |
} | |
*/ | |
export function infallible(t: never): never { | |
throw new Error('Reached infallible but that shouldn\'t be possible.') | |
} | |
export function unimplemented(): never { | |
throw new Error('This codepath has not been implemented.') | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment