Created
April 9, 2020 05:59
-
-
Save anaisbetts/0c0a7c23145aef13f3e1773b239b1907 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
export abstract class Result<T> { | |
abstract isOk(): boolean; | |
abstract isErr(): boolean; | |
abstract ok(): T | undefined; | |
abstract err(): Error | undefined; | |
static Ok<T>(val: T): Result<T> { | |
return new OkValue(val); | |
} | |
static Err<T>(err: Error): Result<T> { | |
return new ErrorValue(err); | |
} | |
static fromPromise<T>(val: Promise<T>): Promise<Result<T>> { | |
return val.then( | |
x => Result.Ok(x), | |
ex => Result.Err(ex)); | |
} | |
expect(): T { | |
if (this.isErr()) { | |
throw new Error('Value is an Error and we expected an Ok'); | |
} | |
return this.ok()!; | |
} | |
expectErr(): Error { | |
if (this.isOk()) { | |
throw new Error('Value is an Error and we expected an Ok'); | |
} | |
return this.err()!; | |
} | |
contains(val: T): boolean { | |
if (this.isErr()) return false; | |
return (this.expect() === val); | |
} | |
map<N>(fn: ((val: T) => N)): Result<N> { | |
if (this.isErr()) { | |
return Result.Err<N>(this.expectErr()); | |
} | |
return Result.Ok(fn(this.expect())); | |
} | |
mapOrElse<N>(orElse: N, fn: ((val: T) => N)): N { | |
if (this.isErr()) return orElse; | |
return fn(this.expect()); | |
} | |
mapErr(fn: ((val: Error) => Error)): Result<T> { | |
if (this.isOk()) return this; | |
return Result.Err(fn(this.expectErr())); | |
} | |
and<N>(res: Result<N>): Result<N> { | |
return this.isOk() ? res : Result.Err(this.expectErr()); | |
} | |
andThen<N>(res: ((val: T) => Result<N>)): Result<N> { | |
return this.isOk() ? res(this.expect()) : Result.Err(this.expectErr()); | |
} | |
or(res: Result<T>): Result<T> { | |
return this.isErr() ? res : this; | |
} | |
orElse(res: ((err: Error) => Result<T>)): Result<T> { | |
return this.isErr() ? res(this.expectErr()) : this; | |
} | |
} | |
class OkValue<T> extends Result<T> { | |
value: T; | |
constructor(val: T) { | |
super(); | |
this.value = val; | |
} | |
isOk(): boolean { | |
return true; | |
} | |
isErr(): boolean { | |
return false; | |
} | |
ok(): T | undefined { | |
return this.value; | |
} | |
err(): Error | undefined { | |
return undefined; | |
} | |
} | |
class ErrorValue<T> extends Result<T> { | |
value: Error; | |
constructor(val: Error) { | |
super(); | |
this.value = val; | |
} | |
isOk(): boolean { | |
return false; | |
} | |
isErr(): boolean { | |
return true; | |
} | |
ok(): T | undefined { | |
return undefined; | |
} | |
err(): Error | undefined { | |
return this.value; | |
} | |
} |
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
import { useEffect, useState } from 'react'; | |
import { from, Observable } from 'rxjs'; | |
import { Result } from './result'; | |
export function useObservable<T>( | |
target: () => Observable<T>, | |
initial?: T, | |
): Result<T | undefined> { | |
const [ret, setter] = useState(Result.Ok(initial)); | |
const [obs] = useState(target); | |
useEffect( | |
() => { | |
const sub = obs.subscribe( | |
x => setter(Result.Ok(x)), | |
ex => setter(Result.Err(ex))); | |
return sub.unsubscribe.bind(sub); | |
}, | |
[obs], | |
); | |
return ret; | |
} | |
export function usePromise<T>( | |
target: () => Promise<T>, | |
initial?: T, | |
): Result<T | undefined> { | |
return useObservable(() => from(target()), initial); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment