diff options
Diffstat (limited to 'frontend/ts/src/lib/loadable.ts')
-rw-r--r-- | frontend/ts/src/lib/loadable.ts | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/frontend/ts/src/lib/loadable.ts b/frontend/ts/src/lib/loadable.ts new file mode 100644 index 0000000..919e0ba --- /dev/null +++ b/frontend/ts/src/lib/loadable.ts @@ -0,0 +1,73 @@ +export type Loadable<T> = Init | Loading | Loaded<T> | Failure + +type Init = { + key: 'INIT' +} + +export const init: Init = { key: 'INIT' } + +export function isInit(l: Loadable<any>): l is Init { + return l.key == 'INIT' +} + +type Loading = { + key: 'LOADING' +} + +export const loading: Loading = { key: 'LOADING' } + +export function isLoading(l: Loadable<any>): l is Loading { + return l.key == 'LOADING' +} + +type Loaded<T> = { + key: 'LOADED', + value: T +} + +export function loaded<T>(value: T): Loaded<T> { + return { key: 'LOADED', value } +} + +export function isLoaded<T>(l: Loadable<T>): l is Loaded<T> { + return l.key == 'LOADED' +} + +type Failure = { + key: 'FAILURE', + error: string +} + +export function failure(error: string): Failure { + return { + key: 'FAILURE', + error + } +} + +export function isFailure(l: Loadable<any>): l is Failure { + return l.key == 'FAILURE' +} + +export function map<A, B>(loadable: Loadable<A>, f: (value: A) => B): Loadable<B> { + if (loadable.key == 'LOADED') { + return loaded(f(loadable.value)) + } else { + return loadable + } +} + +export function map2<A, B, C>(l: [Loadable<A>, Loadable<B>], f: (a: A, b: B) => C): Loadable<C> { + const [l1, l2] = l + if (l1.key == 'FAILURE') { + return l1 + } else if (l2.key == 'FAILURE') { + return l2 + } else if (l1.key == 'LOADING' || l2.key == 'LOADING') { + return loading + } else if (l1.key == 'INIT' || l2.key == 'INIT') { + return init + } else { + return loaded(f(l1.value, l2.value)) + } +} |