aboutsummaryrefslogtreecommitdiff
path: root/frontend/ts/src/lib/loadable.ts
blob: 919e0baea5743558f1974c27db7ce240ccd33314 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
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))
    }
}