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))
}
}
|