return-style
Version:
Non-intrusively convert the result of any function or promise to the user's desired style.
146 lines (126 loc) • 2.75 kB
text/typescript
import { Option } from './option.js'
enum ResultType {
Ok
, Err
}
export class Result<T, E> {
private value?: T
private error?: E
private constructor(type: ResultType.Ok, value: T)
private constructor(type: ResultType.Err, error: E)
private constructor(private type: ResultType, valueOrError: T | E) {
if (type === ResultType.Ok) {
this.value = valueOrError as T
} else {
this.error = valueOrError as E
}
}
static Ok<T, E>(value: T): Result<T, E> {
return new Result(ResultType.Ok, value)
}
static Err<T, E>(error: E): Result<T, E> {
return new Result(ResultType.Err, error)
}
isOk() {
return this.type === ResultType.Ok
}
isErr() {
return this.type === ResultType.Err
}
map<U>(mapper: (val: T) => U): Result<U, E> {
if (this.isOk()) {
return Result.Ok(mapper(this.value!))
} else {
return Result.Err(this.error!)
}
}
mapErr<U>(mapper: (err: E) => U): Result<T, U> {
if (this.isOk()) {
return Result.Ok(this.value!)
} else {
return Result.Err(mapper(this.error!))
}
}
mapOr<U>(defaultValue: U, mapper: (val: T) => U): U {
if (this.isOk()) {
return mapper(this.value!)
} else {
return defaultValue
}
}
mapOrElse<U>(createDefaultValue: (err: E) => U, mapper: (val: T) => U): U {
if (this.isOk()) {
return mapper(this.value!)
} else {
return createDefaultValue(this.error!)
}
}
/**
* @throws {E}
*/
unwrap(): T {
if (this.isOk()) {
return this.value!
} else {
throw this.error!
}
}
unwrapOr<U>(defaultValue: U): T | U {
if (this.isOk()) {
return this.value!
} else {
return defaultValue
}
}
unwrapOrElse<U>(createDefaultValue: (err: E) => U): T | U {
if (this.isOk()) {
return this.value!
} else {
return createDefaultValue(this.error!)
}
}
/**
* @throws {Error}
*/
unwrapErr(): E {
if (this.isErr()) {
return this.error!
} else {
throw new Error('unwrapErr called on a Ok')
}
}
/**
* @throws {Error}
*/
expect(message: string): T {
if (this.isOk()) {
return this.value!
} else {
throw new Error(message, { cause: this.error! })
}
}
/**
* @throws {Error}
*/
expectErr(message: string): E {
if (this.isErr()) {
return this.error!
} else {
throw new Error(message, { cause: this.value! })
}
}
ok(): Option<T> {
if (this.isOk()) {
return Option.Some(this.value!)
} else {
return Option.None()
}
}
err(): Option<E> {
if (this.isOk()) {
return Option.None()
} else {
return Option.Some(this.error!)
}
}
}