@onrails/maybe 0.2.2 → 0.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DESIGN.md +2 -0
- package/dist/fluent.cjs +1 -4
- package/dist/fluent.cjs.map +1 -1
- package/dist/fluent.d.cts +3 -6
- package/dist/fluent.d.ts +3 -6
- package/dist/fluent.js +1 -4
- package/dist/fluent.js.map +1 -1
- package/dist/index.cjs +1 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -244
- package/dist/index.d.ts +2 -244
- package/dist/index.js +1 -4
- package/dist/index.js.map +1 -1
- package/dist/internal/dual.d.cts +11 -0
- package/dist/internal/dual.d.ts +11 -0
- package/dist/interop.cjs +1 -4
- package/dist/interop.cjs.map +1 -1
- package/dist/interop.d.cts +8 -11
- package/dist/interop.d.ts +8 -11
- package/dist/interop.js +1 -4
- package/dist/interop.js.map +1 -1
- package/dist/maybe.d.cts +242 -0
- package/dist/maybe.d.ts +242 -0
- package/package.json +29 -14
package/dist/maybe.d.cts
ADDED
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tagged optional value — a discriminated union over `_tag` where absence
|
|
3
|
+
* (`None`) is an expected outcome, not a failure. Construct with {@link some} /
|
|
4
|
+
* {@link none}, narrow with {@link isSome} / {@link isNone}, and collapse with
|
|
5
|
+
* {@link match}.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* function findUser(id: string): Maybe<User> {
|
|
10
|
+
* return fromNullable(db.users.get(id));
|
|
11
|
+
* }
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
export type Maybe<T> = {
|
|
15
|
+
readonly _tag: "Some";
|
|
16
|
+
readonly value: T;
|
|
17
|
+
} | {
|
|
18
|
+
readonly _tag: "None";
|
|
19
|
+
};
|
|
20
|
+
/** The `Some` branch of a {@link Maybe} — a present value tagged `"Some"`. */
|
|
21
|
+
export type Some<T> = Extract<Maybe<T>, {
|
|
22
|
+
_tag: "Some";
|
|
23
|
+
}>;
|
|
24
|
+
/** The `None` branch of a {@link Maybe} — expected absence, tagged `"None"`. */
|
|
25
|
+
export type None = Extract<Maybe<never>, {
|
|
26
|
+
_tag: "None";
|
|
27
|
+
}>;
|
|
28
|
+
/**
|
|
29
|
+
* Lifts a value into the `Some` branch.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```ts
|
|
33
|
+
* const m = some(1); // Maybe<number>
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export declare const some: <T>(value: T) => Maybe<T>;
|
|
37
|
+
/**
|
|
38
|
+
* Fantasy Land `pure` — alias of {@link some}. One lift name shared across
|
|
39
|
+
* the trio (`of` / `Result.of` / `ResultAsync.of`) for generic and FL-style
|
|
40
|
+
* code.
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```ts
|
|
44
|
+
* const m = of(1); // Maybe<number> — identical to some(1)
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
export declare const of: typeof some;
|
|
48
|
+
/**
|
|
49
|
+
* The `None` value — represents expected absence. Not a failure.
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```ts
|
|
53
|
+
* const cached: Maybe<User> = cache.has(id) ? some(cache.get(id)) : none();
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
export declare const none: <T = never>() => Maybe<T>;
|
|
57
|
+
/**
|
|
58
|
+
* Type-narrowing predicate: returns `true` when the value is `Some`.
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```ts
|
|
62
|
+
* if (isSome(m)) {
|
|
63
|
+
* console.log(m.value); // narrowed to Some branch
|
|
64
|
+
* }
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
export declare const isSome: <T>(maybe: Maybe<T>) => maybe is Some<T>;
|
|
68
|
+
/**
|
|
69
|
+
* Type-narrowing predicate: returns `true` when the value is `None`.
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```ts
|
|
73
|
+
* if (isNone(fromNullable(user))) {
|
|
74
|
+
* return redirect("/login"); // narrowed to None branch
|
|
75
|
+
* }
|
|
76
|
+
* ```
|
|
77
|
+
*/
|
|
78
|
+
export declare const isNone: <T>(maybe: Maybe<T>) => maybe is None;
|
|
79
|
+
/**
|
|
80
|
+
* Lift a nullable value into `Maybe<T>` — `null` and `undefined` become
|
|
81
|
+
* `None`; anything else becomes `Some`.
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* ```ts
|
|
85
|
+
* fromNullable(cache.get(key)); // Maybe<V>
|
|
86
|
+
* fromNullable(null); // None
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
export declare const fromNullable: <T>(value: T | null | undefined) => Maybe<T>;
|
|
90
|
+
/**
|
|
91
|
+
* Transform the `Some` value, passing `None` through unchanged. Dual-form.
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* ```ts
|
|
95
|
+
* map(some(2), (n) => n * 3); // Some 6 — data-first
|
|
96
|
+
* pipe(fromNullable(input), map((s) => s.trim())); // curried
|
|
97
|
+
* ```
|
|
98
|
+
*/
|
|
99
|
+
export declare const map: {
|
|
100
|
+
<T, U>(maybe: Maybe<T>, fn: (value: T) => U): Maybe<U>;
|
|
101
|
+
<T, U>(fn: (value: T) => U): (maybe: Maybe<T>) => Maybe<U>;
|
|
102
|
+
};
|
|
103
|
+
/**
|
|
104
|
+
* Canonical bind for `Maybe`. Chains a `Maybe`-returning step;
|
|
105
|
+
* short-circuits on `None`. Dual-form.
|
|
106
|
+
*
|
|
107
|
+
* @example
|
|
108
|
+
* ```ts
|
|
109
|
+
* flatMap(fromNullable(user), (u) =>
|
|
110
|
+
* u.active ? some(u) : none(),
|
|
111
|
+
* );
|
|
112
|
+
* ```
|
|
113
|
+
*/
|
|
114
|
+
export declare const flatMap: {
|
|
115
|
+
<T, U>(maybe: Maybe<T>, fn: (value: T) => Maybe<U>): Maybe<U>;
|
|
116
|
+
<T, U>(fn: (value: T) => Maybe<U>): (maybe: Maybe<T>) => Maybe<U>;
|
|
117
|
+
};
|
|
118
|
+
/**
|
|
119
|
+
* Neverthrow-compat alias of {@link flatMap} — same dual-form shape. Prefer
|
|
120
|
+
* {@link flatMap} as the canonical name; reach for `andThen` only when porting
|
|
121
|
+
* neverthrow code or matching its vocabulary.
|
|
122
|
+
*
|
|
123
|
+
* @example
|
|
124
|
+
* ```ts
|
|
125
|
+
* andThen(fromNullable(user), (u) =>
|
|
126
|
+
* u.active ? some(u) : none(),
|
|
127
|
+
* );
|
|
128
|
+
* ```
|
|
129
|
+
*/
|
|
130
|
+
export declare const andThen: {
|
|
131
|
+
<T, U>(maybe: Maybe<T>, fn: (value: T) => Maybe<U>): Maybe<U>;
|
|
132
|
+
<T, U>(fn: (value: T) => Maybe<U>): (maybe: Maybe<T>) => Maybe<U>;
|
|
133
|
+
};
|
|
134
|
+
/**
|
|
135
|
+
* Terminal collapse — fold both branches into a single value. Positional,
|
|
136
|
+
* dual-form. Same shape as `Result.match` for sibling consistency.
|
|
137
|
+
*
|
|
138
|
+
* For files that also import `match` from `ts-pattern`, use a namespace
|
|
139
|
+
* import (`import * as Maybe from "@onrails/maybe"` → `Maybe.match`) to
|
|
140
|
+
* dissolve the collision.
|
|
141
|
+
*
|
|
142
|
+
* @example
|
|
143
|
+
* ```ts
|
|
144
|
+
* const greeting = match(
|
|
145
|
+
* fromNullable(user),
|
|
146
|
+
* (u) => `hello ${u.name}`,
|
|
147
|
+
* () => "hello guest",
|
|
148
|
+
* );
|
|
149
|
+
* ```
|
|
150
|
+
*/
|
|
151
|
+
export declare const match: {
|
|
152
|
+
<T, U>(maybe: Maybe<T>, onSome: (value: T) => U, onNone: () => U): U;
|
|
153
|
+
<T, U>(onSome: (value: T) => U, onNone: () => U): (maybe: Maybe<T>) => U;
|
|
154
|
+
};
|
|
155
|
+
export declare const unwrapOr: {
|
|
156
|
+
<T>(maybe: Maybe<T>, defaultValue: T): T;
|
|
157
|
+
<T>(defaultValue: T): (maybe: Maybe<T>) => T;
|
|
158
|
+
};
|
|
159
|
+
/**
|
|
160
|
+
* Unwraps the `Some` value or throws if the value is `None`.
|
|
161
|
+
*
|
|
162
|
+
* @throws when the value is None — assertion-tier; use {@link match} / {@link unwrapOr} in business logic.
|
|
163
|
+
* Allowed in `*.spec.ts` / `*.test.ts`; flagged elsewhere by the plugins.
|
|
164
|
+
*
|
|
165
|
+
* @example
|
|
166
|
+
* ```ts
|
|
167
|
+
* expect(unwrap(parseUser(raw))).toEqual(expected);
|
|
168
|
+
* ```
|
|
169
|
+
*/
|
|
170
|
+
export declare const unwrap: <T>(maybe: Maybe<T>) => T;
|
|
171
|
+
/**
|
|
172
|
+
* Drop every `None` and collect the remaining `Some` values into an array.
|
|
173
|
+
*
|
|
174
|
+
* @example
|
|
175
|
+
* ```ts
|
|
176
|
+
* compact([some(1), none(), some(2)]); // [1, 2]
|
|
177
|
+
* ```
|
|
178
|
+
*/
|
|
179
|
+
export declare const compact: <T>(maybes: readonly Maybe<T>[]) => T[];
|
|
180
|
+
/**
|
|
181
|
+
* `compact(items.map(fn))` — map each item to `Maybe`, drop `None`,
|
|
182
|
+
* collect the rest.
|
|
183
|
+
*
|
|
184
|
+
* @example
|
|
185
|
+
* ```ts
|
|
186
|
+
* compactMap(rawRows, (row) =>
|
|
187
|
+
* row.deletedAt ? none() : some(row.id),
|
|
188
|
+
* );
|
|
189
|
+
* // string[]
|
|
190
|
+
* ```
|
|
191
|
+
*/
|
|
192
|
+
export declare const compactMap: <T, U>(items: readonly T[], fn: (item: T) => Maybe<U>) => U[];
|
|
193
|
+
/**
|
|
194
|
+
* `flatMap(fromNullable(value), fn)` — lift a nullable then bind through
|
|
195
|
+
* a `Maybe`-returning step. Convenient for chaining lookups.
|
|
196
|
+
*
|
|
197
|
+
* @example
|
|
198
|
+
* ```ts
|
|
199
|
+
* optional(rawId, (id) => fromNullable(cache.get(id)));
|
|
200
|
+
* ```
|
|
201
|
+
*/
|
|
202
|
+
export declare const optional: <T, U>(value: T | null | undefined, fn: (value: T) => Maybe<U>) => Maybe<U>;
|
|
203
|
+
/**
|
|
204
|
+
* Run a side effect on the `Some` value, pass the `Maybe` through unchanged.
|
|
205
|
+
* `None` is a no-op. Mirrors `tap` from `@onrails/result`. Dual-form.
|
|
206
|
+
*
|
|
207
|
+
* @example
|
|
208
|
+
* ```ts
|
|
209
|
+
* tap(some(2), (n) => console.log(n)); // logs 2, returns Some 2
|
|
210
|
+
* pipe(fromNullable(row), tap((r) => sink.push(r))); // curried — collect on Some
|
|
211
|
+
* ```
|
|
212
|
+
*/
|
|
213
|
+
export declare const tap: {
|
|
214
|
+
<T>(maybe: Maybe<T>, fn: (value: T) => void): Maybe<T>;
|
|
215
|
+
<T>(fn: (value: T) => void): (maybe: Maybe<T>) => Maybe<T>;
|
|
216
|
+
};
|
|
217
|
+
/**
|
|
218
|
+
* Run a side effect when the `Maybe` is `None`, pass it through unchanged.
|
|
219
|
+
* `Some` is a no-op. The `None`-side mirror of {@link tap}. Dual-form.
|
|
220
|
+
*
|
|
221
|
+
* @example
|
|
222
|
+
* ```ts
|
|
223
|
+
* tapNone(none(), () => metrics.miss()); // runs effect, returns None
|
|
224
|
+
* pipe(fromNullable(hit), tapNone(() => metrics.miss())); // curried
|
|
225
|
+
* ```
|
|
226
|
+
*/
|
|
227
|
+
export declare const tapNone: {
|
|
228
|
+
<T>(maybe: Maybe<T>, fn: () => void): Maybe<T>;
|
|
229
|
+
<T>(fn: () => void): (maybe: Maybe<T>) => Maybe<T>;
|
|
230
|
+
};
|
|
231
|
+
/**
|
|
232
|
+
* Debug printer — renders a maybe as `Some(…)` / `None` for logs. Payloads
|
|
233
|
+
* print as JSON (values are plain data by design); non-JSON payloads fall
|
|
234
|
+
* back to `String(...)`. Mirror of the result package's `show`.
|
|
235
|
+
*
|
|
236
|
+
* @example
|
|
237
|
+
* ```ts
|
|
238
|
+
* show(some(1)); // 'Some(1)'
|
|
239
|
+
* show(none()); // 'None'
|
|
240
|
+
* ```
|
|
241
|
+
*/
|
|
242
|
+
export declare const show: <T>(maybe: Maybe<T>) => string;
|
package/dist/maybe.d.ts
ADDED
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tagged optional value — a discriminated union over `_tag` where absence
|
|
3
|
+
* (`None`) is an expected outcome, not a failure. Construct with {@link some} /
|
|
4
|
+
* {@link none}, narrow with {@link isSome} / {@link isNone}, and collapse with
|
|
5
|
+
* {@link match}.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* function findUser(id: string): Maybe<User> {
|
|
10
|
+
* return fromNullable(db.users.get(id));
|
|
11
|
+
* }
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
export type Maybe<T> = {
|
|
15
|
+
readonly _tag: "Some";
|
|
16
|
+
readonly value: T;
|
|
17
|
+
} | {
|
|
18
|
+
readonly _tag: "None";
|
|
19
|
+
};
|
|
20
|
+
/** The `Some` branch of a {@link Maybe} — a present value tagged `"Some"`. */
|
|
21
|
+
export type Some<T> = Extract<Maybe<T>, {
|
|
22
|
+
_tag: "Some";
|
|
23
|
+
}>;
|
|
24
|
+
/** The `None` branch of a {@link Maybe} — expected absence, tagged `"None"`. */
|
|
25
|
+
export type None = Extract<Maybe<never>, {
|
|
26
|
+
_tag: "None";
|
|
27
|
+
}>;
|
|
28
|
+
/**
|
|
29
|
+
* Lifts a value into the `Some` branch.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```ts
|
|
33
|
+
* const m = some(1); // Maybe<number>
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export declare const some: <T>(value: T) => Maybe<T>;
|
|
37
|
+
/**
|
|
38
|
+
* Fantasy Land `pure` — alias of {@link some}. One lift name shared across
|
|
39
|
+
* the trio (`of` / `Result.of` / `ResultAsync.of`) for generic and FL-style
|
|
40
|
+
* code.
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```ts
|
|
44
|
+
* const m = of(1); // Maybe<number> — identical to some(1)
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
export declare const of: typeof some;
|
|
48
|
+
/**
|
|
49
|
+
* The `None` value — represents expected absence. Not a failure.
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```ts
|
|
53
|
+
* const cached: Maybe<User> = cache.has(id) ? some(cache.get(id)) : none();
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
export declare const none: <T = never>() => Maybe<T>;
|
|
57
|
+
/**
|
|
58
|
+
* Type-narrowing predicate: returns `true` when the value is `Some`.
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```ts
|
|
62
|
+
* if (isSome(m)) {
|
|
63
|
+
* console.log(m.value); // narrowed to Some branch
|
|
64
|
+
* }
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
export declare const isSome: <T>(maybe: Maybe<T>) => maybe is Some<T>;
|
|
68
|
+
/**
|
|
69
|
+
* Type-narrowing predicate: returns `true` when the value is `None`.
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```ts
|
|
73
|
+
* if (isNone(fromNullable(user))) {
|
|
74
|
+
* return redirect("/login"); // narrowed to None branch
|
|
75
|
+
* }
|
|
76
|
+
* ```
|
|
77
|
+
*/
|
|
78
|
+
export declare const isNone: <T>(maybe: Maybe<T>) => maybe is None;
|
|
79
|
+
/**
|
|
80
|
+
* Lift a nullable value into `Maybe<T>` — `null` and `undefined` become
|
|
81
|
+
* `None`; anything else becomes `Some`.
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* ```ts
|
|
85
|
+
* fromNullable(cache.get(key)); // Maybe<V>
|
|
86
|
+
* fromNullable(null); // None
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
export declare const fromNullable: <T>(value: T | null | undefined) => Maybe<T>;
|
|
90
|
+
/**
|
|
91
|
+
* Transform the `Some` value, passing `None` through unchanged. Dual-form.
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* ```ts
|
|
95
|
+
* map(some(2), (n) => n * 3); // Some 6 — data-first
|
|
96
|
+
* pipe(fromNullable(input), map((s) => s.trim())); // curried
|
|
97
|
+
* ```
|
|
98
|
+
*/
|
|
99
|
+
export declare const map: {
|
|
100
|
+
<T, U>(maybe: Maybe<T>, fn: (value: T) => U): Maybe<U>;
|
|
101
|
+
<T, U>(fn: (value: T) => U): (maybe: Maybe<T>) => Maybe<U>;
|
|
102
|
+
};
|
|
103
|
+
/**
|
|
104
|
+
* Canonical bind for `Maybe`. Chains a `Maybe`-returning step;
|
|
105
|
+
* short-circuits on `None`. Dual-form.
|
|
106
|
+
*
|
|
107
|
+
* @example
|
|
108
|
+
* ```ts
|
|
109
|
+
* flatMap(fromNullable(user), (u) =>
|
|
110
|
+
* u.active ? some(u) : none(),
|
|
111
|
+
* );
|
|
112
|
+
* ```
|
|
113
|
+
*/
|
|
114
|
+
export declare const flatMap: {
|
|
115
|
+
<T, U>(maybe: Maybe<T>, fn: (value: T) => Maybe<U>): Maybe<U>;
|
|
116
|
+
<T, U>(fn: (value: T) => Maybe<U>): (maybe: Maybe<T>) => Maybe<U>;
|
|
117
|
+
};
|
|
118
|
+
/**
|
|
119
|
+
* Neverthrow-compat alias of {@link flatMap} — same dual-form shape. Prefer
|
|
120
|
+
* {@link flatMap} as the canonical name; reach for `andThen` only when porting
|
|
121
|
+
* neverthrow code or matching its vocabulary.
|
|
122
|
+
*
|
|
123
|
+
* @example
|
|
124
|
+
* ```ts
|
|
125
|
+
* andThen(fromNullable(user), (u) =>
|
|
126
|
+
* u.active ? some(u) : none(),
|
|
127
|
+
* );
|
|
128
|
+
* ```
|
|
129
|
+
*/
|
|
130
|
+
export declare const andThen: {
|
|
131
|
+
<T, U>(maybe: Maybe<T>, fn: (value: T) => Maybe<U>): Maybe<U>;
|
|
132
|
+
<T, U>(fn: (value: T) => Maybe<U>): (maybe: Maybe<T>) => Maybe<U>;
|
|
133
|
+
};
|
|
134
|
+
/**
|
|
135
|
+
* Terminal collapse — fold both branches into a single value. Positional,
|
|
136
|
+
* dual-form. Same shape as `Result.match` for sibling consistency.
|
|
137
|
+
*
|
|
138
|
+
* For files that also import `match` from `ts-pattern`, use a namespace
|
|
139
|
+
* import (`import * as Maybe from "@onrails/maybe"` → `Maybe.match`) to
|
|
140
|
+
* dissolve the collision.
|
|
141
|
+
*
|
|
142
|
+
* @example
|
|
143
|
+
* ```ts
|
|
144
|
+
* const greeting = match(
|
|
145
|
+
* fromNullable(user),
|
|
146
|
+
* (u) => `hello ${u.name}`,
|
|
147
|
+
* () => "hello guest",
|
|
148
|
+
* );
|
|
149
|
+
* ```
|
|
150
|
+
*/
|
|
151
|
+
export declare const match: {
|
|
152
|
+
<T, U>(maybe: Maybe<T>, onSome: (value: T) => U, onNone: () => U): U;
|
|
153
|
+
<T, U>(onSome: (value: T) => U, onNone: () => U): (maybe: Maybe<T>) => U;
|
|
154
|
+
};
|
|
155
|
+
export declare const unwrapOr: {
|
|
156
|
+
<T>(maybe: Maybe<T>, defaultValue: T): T;
|
|
157
|
+
<T>(defaultValue: T): (maybe: Maybe<T>) => T;
|
|
158
|
+
};
|
|
159
|
+
/**
|
|
160
|
+
* Unwraps the `Some` value or throws if the value is `None`.
|
|
161
|
+
*
|
|
162
|
+
* @throws when the value is None — assertion-tier; use {@link match} / {@link unwrapOr} in business logic.
|
|
163
|
+
* Allowed in `*.spec.ts` / `*.test.ts`; flagged elsewhere by the plugins.
|
|
164
|
+
*
|
|
165
|
+
* @example
|
|
166
|
+
* ```ts
|
|
167
|
+
* expect(unwrap(parseUser(raw))).toEqual(expected);
|
|
168
|
+
* ```
|
|
169
|
+
*/
|
|
170
|
+
export declare const unwrap: <T>(maybe: Maybe<T>) => T;
|
|
171
|
+
/**
|
|
172
|
+
* Drop every `None` and collect the remaining `Some` values into an array.
|
|
173
|
+
*
|
|
174
|
+
* @example
|
|
175
|
+
* ```ts
|
|
176
|
+
* compact([some(1), none(), some(2)]); // [1, 2]
|
|
177
|
+
* ```
|
|
178
|
+
*/
|
|
179
|
+
export declare const compact: <T>(maybes: readonly Maybe<T>[]) => T[];
|
|
180
|
+
/**
|
|
181
|
+
* `compact(items.map(fn))` — map each item to `Maybe`, drop `None`,
|
|
182
|
+
* collect the rest.
|
|
183
|
+
*
|
|
184
|
+
* @example
|
|
185
|
+
* ```ts
|
|
186
|
+
* compactMap(rawRows, (row) =>
|
|
187
|
+
* row.deletedAt ? none() : some(row.id),
|
|
188
|
+
* );
|
|
189
|
+
* // string[]
|
|
190
|
+
* ```
|
|
191
|
+
*/
|
|
192
|
+
export declare const compactMap: <T, U>(items: readonly T[], fn: (item: T) => Maybe<U>) => U[];
|
|
193
|
+
/**
|
|
194
|
+
* `flatMap(fromNullable(value), fn)` — lift a nullable then bind through
|
|
195
|
+
* a `Maybe`-returning step. Convenient for chaining lookups.
|
|
196
|
+
*
|
|
197
|
+
* @example
|
|
198
|
+
* ```ts
|
|
199
|
+
* optional(rawId, (id) => fromNullable(cache.get(id)));
|
|
200
|
+
* ```
|
|
201
|
+
*/
|
|
202
|
+
export declare const optional: <T, U>(value: T | null | undefined, fn: (value: T) => Maybe<U>) => Maybe<U>;
|
|
203
|
+
/**
|
|
204
|
+
* Run a side effect on the `Some` value, pass the `Maybe` through unchanged.
|
|
205
|
+
* `None` is a no-op. Mirrors `tap` from `@onrails/result`. Dual-form.
|
|
206
|
+
*
|
|
207
|
+
* @example
|
|
208
|
+
* ```ts
|
|
209
|
+
* tap(some(2), (n) => console.log(n)); // logs 2, returns Some 2
|
|
210
|
+
* pipe(fromNullable(row), tap((r) => sink.push(r))); // curried — collect on Some
|
|
211
|
+
* ```
|
|
212
|
+
*/
|
|
213
|
+
export declare const tap: {
|
|
214
|
+
<T>(maybe: Maybe<T>, fn: (value: T) => void): Maybe<T>;
|
|
215
|
+
<T>(fn: (value: T) => void): (maybe: Maybe<T>) => Maybe<T>;
|
|
216
|
+
};
|
|
217
|
+
/**
|
|
218
|
+
* Run a side effect when the `Maybe` is `None`, pass it through unchanged.
|
|
219
|
+
* `Some` is a no-op. The `None`-side mirror of {@link tap}. Dual-form.
|
|
220
|
+
*
|
|
221
|
+
* @example
|
|
222
|
+
* ```ts
|
|
223
|
+
* tapNone(none(), () => metrics.miss()); // runs effect, returns None
|
|
224
|
+
* pipe(fromNullable(hit), tapNone(() => metrics.miss())); // curried
|
|
225
|
+
* ```
|
|
226
|
+
*/
|
|
227
|
+
export declare const tapNone: {
|
|
228
|
+
<T>(maybe: Maybe<T>, fn: () => void): Maybe<T>;
|
|
229
|
+
<T>(fn: () => void): (maybe: Maybe<T>) => Maybe<T>;
|
|
230
|
+
};
|
|
231
|
+
/**
|
|
232
|
+
* Debug printer — renders a maybe as `Some(…)` / `None` for logs. Payloads
|
|
233
|
+
* print as JSON (values are plain data by design); non-JSON payloads fall
|
|
234
|
+
* back to `String(...)`. Mirror of the result package's `show`.
|
|
235
|
+
*
|
|
236
|
+
* @example
|
|
237
|
+
* ```ts
|
|
238
|
+
* show(some(1)); // 'Some(1)'
|
|
239
|
+
* show(none()); // 'None'
|
|
240
|
+
* ```
|
|
241
|
+
*/
|
|
242
|
+
export declare const show: <T>(maybe: Maybe<T>) => string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onrails/maybe",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.5",
|
|
4
4
|
"description": "Tagged Maybe for expected absence — pure tagged unions, Result interop, tree-shakeable",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Alan R. Soares",
|
|
@@ -43,23 +43,38 @@
|
|
|
43
43
|
],
|
|
44
44
|
"exports": {
|
|
45
45
|
".": {
|
|
46
|
-
"
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
"import": {
|
|
47
|
+
"types": "./dist/index.d.ts",
|
|
48
|
+
"default": "./dist/index.js"
|
|
49
|
+
},
|
|
50
|
+
"require": {
|
|
51
|
+
"types": "./dist/index.d.cts",
|
|
52
|
+
"default": "./dist/index.cjs"
|
|
53
|
+
}
|
|
49
54
|
},
|
|
50
55
|
"./fluent": {
|
|
51
|
-
"
|
|
52
|
-
|
|
53
|
-
|
|
56
|
+
"import": {
|
|
57
|
+
"types": "./dist/fluent.d.ts",
|
|
58
|
+
"default": "./dist/fluent.js"
|
|
59
|
+
},
|
|
60
|
+
"require": {
|
|
61
|
+
"types": "./dist/fluent.d.cts",
|
|
62
|
+
"default": "./dist/fluent.cjs"
|
|
63
|
+
}
|
|
54
64
|
},
|
|
55
65
|
"./interop": {
|
|
56
|
-
"
|
|
57
|
-
|
|
58
|
-
|
|
66
|
+
"import": {
|
|
67
|
+
"types": "./dist/interop.d.ts",
|
|
68
|
+
"default": "./dist/interop.js"
|
|
69
|
+
},
|
|
70
|
+
"require": {
|
|
71
|
+
"types": "./dist/interop.d.cts",
|
|
72
|
+
"default": "./dist/interop.cjs"
|
|
73
|
+
}
|
|
59
74
|
}
|
|
60
75
|
},
|
|
61
76
|
"peerDependencies": {
|
|
62
|
-
"@onrails/result": "0.
|
|
77
|
+
"@onrails/result": "^0.4.0"
|
|
63
78
|
},
|
|
64
79
|
"peerDependenciesMeta": {
|
|
65
80
|
"@onrails/result": {
|
|
@@ -70,13 +85,13 @@
|
|
|
70
85
|
"typecheck": "tsc --noEmit",
|
|
71
86
|
"test": "bun test",
|
|
72
87
|
"check": "bun typecheck && bun test",
|
|
73
|
-
"build": "tsup",
|
|
88
|
+
"build": "tsup && tsc -p tsconfig.build.json && bun run ../../scripts/dts-to-cts.ts",
|
|
74
89
|
"clean": "rm -rf dist",
|
|
75
90
|
"prepublishOnly": "bun run build"
|
|
76
91
|
},
|
|
77
92
|
"devDependencies": {
|
|
78
|
-
"@onrails/result": "0.
|
|
79
|
-
"fast-check": "^
|
|
93
|
+
"@onrails/result": "0.4.0",
|
|
94
|
+
"fast-check": "^4.9.0",
|
|
80
95
|
"ts-expect": "^1.3.0",
|
|
81
96
|
"tsup": "^8.5.1"
|
|
82
97
|
}
|