-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathoptional-pair.ts
More file actions
127 lines (116 loc) · 2.86 KB
/
Copy pathoptional-pair.ts
File metadata and controls
127 lines (116 loc) · 2.86 KB
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
import { Optional, toOptional, None } from "./optional.js";
import { Func, nonNullable } from "./util.types.js";
import { Variant, variant, VariantTypeClass } from "./variant.js";
type OptionalPairVariants<A extends nonNullable, B extends nonNullable> =
| Variant<"First", [first: A]>
| Variant<"Second", [second: B]>
| Variant<"Both", [first: A, second: B]>
| Variant<"Neither">;
class OptionalPair<
A extends nonNullable,
B extends nonNullable
> extends VariantTypeClass<OptionalPairVariants<A, B>> {
first(): Optional<A> {
return this.match({
First(first) {
return toOptional(first);
},
Both(first) {
return toOptional(first);
},
_() {
return None;
},
});
}
second(): Optional<B> {
return this.match({
Second(value) {
return toOptional(value);
},
Both(_, second) {
return toOptional(second);
},
_() {
return None;
},
});
}
both(): Optional<Readonly<[first: A, second: B]>> {
return this.match({
Both(first, second) {
return toOptional([first, second] as const);
},
_() {
return None;
},
});
}
combineBoth<C extends nonNullable>(
combine: Func<[first: A, second: B], C>
): Optional<C> {
return this.match({
Both(first, second) {
return toOptional(combine(first, second));
},
_() {
return None;
},
});
}
}
const Neither = new OptionalPair<never, never>(variant("Neither"));
const First = <A extends nonNullable, B extends nonNullable>(
first: Optional<A>
): OptionalPair<A, B> =>
first.match({
Some(value) {
return new OptionalPair<A, B>(variant("First", value));
},
None() {
return Neither;
},
});
const Second = <A extends nonNullable, B extends nonNullable>(
second: Optional<B>
): OptionalPair<A, B> =>
second.match({
Some(value) {
return new OptionalPair<A, B>(variant("Second", value));
},
None() {
return Neither;
},
});
const Both = <A extends nonNullable, B extends nonNullable>(
first: Optional<A>,
second: Optional<B>
): OptionalPair<A, B> =>
first.match({
Some(first) {
return second.match({
Some(second) {
return new OptionalPair<A, B>(variant("Both", first, second));
},
None() {
return new OptionalPair<A, B>(variant("First", first));
},
});
},
None() {
return second.match({
Some(second) {
return new OptionalPair<A, B>(variant("Second", second));
},
None() {
return Neither;
},
});
},
});
const toOptionalPair = <A, B>(
first: A,
second: B
): OptionalPair<NonNullable<A>, NonNullable<B>> =>
Both(toOptional(first), toOptional(second));
export { type OptionalPair, Neither, First, Second, Both, toOptionalPair };