unthrown 3.1.0 → 4.1.0

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/dist/index.cjs CHANGED
@@ -1,8 +1,8 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  //#region src/core.ts
3
3
  /**
4
- * Thrown by a {@link Result}'s `unwrap` / `unwrapErr` when the assertion is
5
- * wrong on a *modeled* result — `unwrap()` on an `Err`, or `unwrapErr()` on an
4
+ * Thrown by a {@link Result}'s `get` / `getErr` when the assertion is
5
+ * wrong on a *modeled* result — `get()` on an `Err`, or `getErr()` on an
6
6
  * `Ok`.
7
7
  *
8
8
  * @remarks
@@ -14,14 +14,19 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
14
14
  * A `Defect` is never wrapped in an `UnwrapError`: its original cause is
15
15
  * re-thrown (with its original stack) instead.
16
16
  *
17
+ * `get()` and `getErr()` are type-gated (`this: Result<T, never>` /
18
+ * `Result<never, E>`), so the wrong-variant branch that throws this is
19
+ * unreachable through well-typed code — it remains only as a defensive guard
20
+ * against unsound runtime misuse (e.g. an `as` cast past the gate).
21
+ *
17
22
  * @typeParam E - the type of the {@link UnwrapError.error} it carries.
18
23
  *
19
24
  * @category Errors
20
25
  */
21
26
  var UnwrapError = class extends Error {
22
27
  /**
23
- * The offending value: the `Err` error for `unwrap()`, or the `Ok` value for
24
- * `unwrapErr()`.
28
+ * The offending value: the `Err` error for `get()`, or the `Ok` value for
29
+ * `getErr()`.
25
30
  */
26
31
  error;
27
32
  constructor(error) {
@@ -109,7 +114,7 @@ var Res = class {
109
114
  return defectRes(cause);
110
115
  }
111
116
  }
112
- orElse(f) {
117
+ flatMapErr(f) {
113
118
  if (this.tag !== "Err") return passThrough(this);
114
119
  try {
115
120
  return f(this.error);
@@ -117,7 +122,11 @@ var Res = class {
117
122
  return defectRes(cause);
118
123
  }
119
124
  }
120
- recover(f) {
125
+ /** @deprecated Use {@link Res.flatMapErr}. */
126
+ orElse(f) {
127
+ return this.flatMapErr(f);
128
+ }
129
+ recoverErr(f) {
121
130
  if (this.tag !== "Err") return passThrough(this);
122
131
  try {
123
132
  return okRes(f(this.error));
@@ -125,6 +134,10 @@ var Res = class {
125
134
  return defectRes(cause);
126
135
  }
127
136
  }
137
+ /** @deprecated Use {@link Res.recoverErr}. */
138
+ recover(f) {
139
+ return this.recoverErr(f);
140
+ }
128
141
  tapErr(f) {
129
142
  if (this.tag !== "Err") return this;
130
143
  try {
@@ -167,30 +180,46 @@ var Res = class {
167
180
  case "Defect": return cases.defect(this.cause);
168
181
  }
169
182
  }
170
- unwrap() {
183
+ get() {
171
184
  switch (this.tag) {
172
185
  case "Ok": return this.value;
173
186
  case "Err": throw new UnwrapError(this.error);
174
187
  case "Defect": throw this.cause;
175
188
  }
176
189
  }
177
- unwrapErr() {
190
+ /** @deprecated Use {@link Res.get}. */
191
+ unwrap() {
192
+ return this.get();
193
+ }
194
+ getErr() {
178
195
  switch (this.tag) {
179
196
  case "Err": return this.error;
180
197
  case "Ok": throw new UnwrapError(this.value);
181
198
  case "Defect": throw this.cause;
182
199
  }
183
200
  }
184
- unwrapOr(fallback) {
201
+ /** @deprecated Use {@link Res.getErr}. */
202
+ unwrapErr() {
203
+ return this.getErr();
204
+ }
205
+ getOr(fallback) {
185
206
  if (this.tag === "Ok") return this.value;
186
207
  if (this.tag === "Defect") throw this.cause;
187
208
  return fallback;
188
209
  }
189
- unwrapOrElse(f) {
210
+ /** @deprecated Use {@link Res.getOr}. */
211
+ unwrapOr(fallback) {
212
+ return this.getOr(fallback);
213
+ }
214
+ getOrElse(f) {
190
215
  if (this.tag === "Ok") return this.value;
191
216
  if (this.tag === "Defect") throw this.cause;
192
217
  return f(this.error);
193
218
  }
219
+ /** @deprecated Use {@link Res.getOrElse}. */
220
+ unwrapOrElse(f) {
221
+ return this.getOrElse(f);
222
+ }
194
223
  getOrNull() {
195
224
  if (this.tag === "Ok") return this.value;
196
225
  if (this.tag === "Defect") throw this.cause;
@@ -200,6 +229,11 @@ var Res = class {
200
229
  if (this.tag === "Ok") return this.value;
201
230
  if (this.tag === "Defect") throw this.cause;
202
231
  }
232
+ getOrThrow() {
233
+ if (this.tag === "Ok") return this.value;
234
+ if (this.tag === "Defect") throw this.cause;
235
+ throw this.error;
236
+ }
203
237
  isOk() {
204
238
  return this.tag === "Ok";
205
239
  }
@@ -421,7 +455,7 @@ var AsyncRes = class AsyncRes {
421
455
  }
422
456
  }));
423
457
  }
424
- orElse(f) {
458
+ flatMapErr(f) {
425
459
  return new AsyncRes(this.promise.then(async (r) => {
426
460
  if (r.tag !== "Err") return passThrough(r);
427
461
  try {
@@ -431,7 +465,11 @@ var AsyncRes = class AsyncRes {
431
465
  }
432
466
  }));
433
467
  }
434
- recover(f) {
468
+ /** @deprecated Use {@link AsyncRes.flatMapErr}. */
469
+ orElse(f) {
470
+ return this.flatMapErr(f);
471
+ }
472
+ recoverErr(f) {
435
473
  return new AsyncRes(this.promise.then((r) => {
436
474
  if (r.tag !== "Err") return passThrough(r);
437
475
  try {
@@ -441,6 +479,10 @@ var AsyncRes = class AsyncRes {
441
479
  }
442
480
  }));
443
481
  }
482
+ /** @deprecated Use {@link AsyncRes.recoverErr}. */
483
+ recover(f) {
484
+ return this.recoverErr(f);
485
+ }
444
486
  tapErr(f) {
445
487
  return new AsyncRes(this.promise.then((r) => {
446
488
  if (r.tag !== "Err") return r;
@@ -487,17 +529,33 @@ var AsyncRes = class AsyncRes {
487
529
  match(cases) {
488
530
  return this.promise.then((r) => r.match(cases));
489
531
  }
532
+ get() {
533
+ return this.promise.then((r) => r.get());
534
+ }
535
+ /** @deprecated Use {@link AsyncRes.get}. */
490
536
  unwrap() {
491
- return this.promise.then((r) => r.unwrap());
537
+ return this.get();
538
+ }
539
+ getErr() {
540
+ return this.promise.then((r) => r.getErr());
492
541
  }
542
+ /** @deprecated Use {@link AsyncRes.getErr}. */
493
543
  unwrapErr() {
494
- return this.promise.then((r) => r.unwrapErr());
544
+ return this.getErr();
545
+ }
546
+ getOr(fallback) {
547
+ return this.promise.then((r) => r.getOr(fallback));
495
548
  }
549
+ /** @deprecated Use {@link AsyncRes.getOr}. */
496
550
  unwrapOr(fallback) {
497
- return this.promise.then((r) => r.unwrapOr(fallback));
551
+ return this.getOr(fallback);
498
552
  }
553
+ getOrElse(f) {
554
+ return this.promise.then((r) => r.getOrElse(f));
555
+ }
556
+ /** @deprecated Use {@link AsyncRes.getOrElse}. */
499
557
  unwrapOrElse(f) {
500
- return this.promise.then((r) => r.unwrapOrElse(f));
558
+ return this.getOrElse(f);
501
559
  }
502
560
  getOrNull() {
503
561
  return this.promise.then((r) => r.getOrNull());
@@ -505,6 +563,9 @@ var AsyncRes = class AsyncRes {
505
563
  getOrUndefined() {
506
564
  return this.promise.then((r) => r.getOrUndefined());
507
565
  }
566
+ getOrThrow() {
567
+ return this.promise.then((r) => r.getOrThrow());
568
+ }
508
569
  };
509
570
  //#endregion
510
571
  //#region src/constructors.ts
@@ -519,7 +580,7 @@ var AsyncRes = class AsyncRes {
519
580
  * import { Ok } from "unthrown";
520
581
  *
521
582
  * Ok(2).map((n) => n + 1); // => Ok(3)
522
- * Ok(42).unwrap(); // => 42
583
+ * Ok(42).get(); // => 42
523
584
  * ```
524
585
  *
525
586
  * @category Constructors
@@ -538,7 +599,7 @@ function Ok(value) {
538
599
  * import { Err } from "unthrown";
539
600
  *
540
601
  * Err("not_found").map((n) => n + 1); // => Err("not_found") (map skipped)
541
- * Err("not_found").unwrapErr(); // => "not_found"
602
+ * Err("not_found").getErr(); // => "not_found"
542
603
  * ```
543
604
  *
544
605
  * @category Constructors
@@ -547,6 +608,58 @@ function Err(error) {
547
608
  return errRes(error);
548
609
  }
549
610
  /**
611
+ * Construct a successful {@link AsyncResult} from a pure value — the pre-lifted
612
+ * form of {@link Ok}, sparing you `Ok(value).toAsync()`.
613
+ *
614
+ * @remarks
615
+ * Reach for this on the synchronous/early branch of an `AsyncResult`-returning
616
+ * function, so both branches share one return type without a trailing
617
+ * `.toAsync()`. Named with the `Async` suffix the async free functions carry
618
+ * (`allAsync`, `allFromDictAsync`); the {@link AsyncResult} companion aliases it
619
+ * as `AsyncResult.Ok` (the namespace already says "async", so the suffix drops).
620
+ *
621
+ * @typeParam T - the success value type.
622
+ * @param value - the success value to wrap.
623
+ *
624
+ * @example
625
+ * ```ts
626
+ * import { OkAsync, type AsyncResult } from "unthrown";
627
+ *
628
+ * function loadItems(ids: string[]): AsyncResult<Item[], never> {
629
+ * if (ids.length === 0) return OkAsync([]); // no more Ok([]).toAsync()
630
+ * return itemRepository.load(ids);
631
+ * }
632
+ * ```
633
+ *
634
+ * @category Constructors
635
+ */
636
+ function OkAsync(value) {
637
+ return Ok(value).toAsync();
638
+ }
639
+ /**
640
+ * Construct a failed {@link AsyncResult} carrying a **modeled** error — the
641
+ * pre-lifted form of {@link Err}, sparing you `Err(error).toAsync()`.
642
+ *
643
+ * @remarks
644
+ * The error-channel mirror of {@link OkAsync}; see it for the naming and the
645
+ * `AsyncResult.Err` companion alias.
646
+ *
647
+ * @typeParam E - the modeled error type.
648
+ * @param error - the domain error to wrap.
649
+ *
650
+ * @example
651
+ * ```ts
652
+ * import { ErrAsync } from "unthrown";
653
+ *
654
+ * ErrAsync("not_found"); // AsyncResult<never, string>
655
+ * ```
656
+ *
657
+ * @category Constructors
658
+ */
659
+ function ErrAsync(error) {
660
+ return Err(error).toAsync();
661
+ }
662
+ /**
550
663
  * Type guard: narrow a {@link Result} to its `Ok` variant, exposing `.value`.
551
664
  *
552
665
  * @returns `true` when `r` is `Ok`.
@@ -713,9 +826,9 @@ function isDefectMarker(x) {
713
826
  * import { fromNullable } from "unthrown";
714
827
  *
715
828
  * const map = new Map([["a", 1]]);
716
- * fromNullable(map.get("a"), () => "absent").unwrap(); // => 1
829
+ * fromNullable(map.get("a"), () => "absent").getOr(0); // => 1
717
830
  * fromNullable(map.get("z"), () => "absent"); // => Err("absent")
718
- * fromNullable(0, () => "absent").unwrap(); // => 0 (falsy but present)
831
+ * fromNullable(0, () => "absent").getOr(-1); // => 0 (falsy but present)
719
832
  * ```
720
833
  */
721
834
  function fromNullable(value, onAbsent) {
@@ -735,7 +848,7 @@ function fromNullable(value, onAbsent) {
735
848
  * `qualify`'s return is **subtracted** from `E`, never inferred into it. So a
736
849
  * `qualify` that returns *only* `defect(cause)` yields `E = never` (a Defect is
737
850
  * out-of-band and must not pollute the error channel); reach for
738
- * {@link fromSafePromise} when every failure is a Defect.
851
+ * {@link fromSafeThrowable} when every throw is a Defect.
739
852
  *
740
853
  * @typeParam A - the wrapped function's argument tuple.
741
854
  * @typeParam T - the wrapped function's return type.
@@ -759,7 +872,7 @@ function fromNullable(value, onAbsent) {
759
872
  * cause instanceof SyntaxError ? ("invalid_json" as const) : defect(cause),
760
873
  * );
761
874
  *
762
- * parse('{"ok":true}').unwrap(); // => { ok: true }
875
+ * parse('{"ok":true}').getOr(null); // => { ok: true }
763
876
  * parse("nope"); // => Err("invalid_json")
764
877
  * ```
765
878
  */
@@ -774,6 +887,44 @@ function fromThrowable(fn, qualify) {
774
887
  };
775
888
  }
776
889
  /**
890
+ * Wrap a throwing synchronous function asserted **not** to fail in any modeled
891
+ * way: any throw becomes a `Defect`.
892
+ *
893
+ * @remarks
894
+ * The synchronous counterpart of {@link fromSafePromise}. Use it only when a
895
+ * throw genuinely indicates a bug rather than an anticipated outcome — the
896
+ * error channel is `never`, so there is nothing to triage; there is no
897
+ * `qualify`. When some throws *are* anticipated, reach for
898
+ * {@link fromThrowable} and triage them.
899
+ *
900
+ * @typeParam A - the wrapped function's argument tuple.
901
+ * @typeParam T - the wrapped function's return type.
902
+ * @param fn - the throwing function to wrap.
903
+ * @returns a function with the same arguments returning `Result<T, never>`.
904
+ *
905
+ * @category Interop
906
+ *
907
+ * @example
908
+ * ```ts
909
+ * import { fromSafeThrowable } from "unthrown";
910
+ *
911
+ * // A decode failure here is a bug (the row came from our own schema), so
912
+ * // every throw is a defect — no throwaway `(cause, defect) => defect(cause)`.
913
+ * const decode = fromSafeThrowable((row: Row) => userSchema.parse(row));
914
+ *
915
+ * decode(row); // => Result<User, never> — a throw becomes a Defect
916
+ * ```
917
+ */
918
+ function fromSafeThrowable(fn) {
919
+ return (...args) => {
920
+ try {
921
+ return Ok(fn(...args));
922
+ } catch (cause) {
923
+ return defectRes(cause);
924
+ }
925
+ };
926
+ }
927
+ /**
777
928
  * Wrap a `Promise` (or a thunk producing one) as an {@link AsyncResult}, forcing
778
929
  * every rejection to be triaged.
779
930
  *
@@ -806,8 +957,8 @@ function fromThrowable(fn, qualify) {
806
957
  * cause instanceof NotFoundError ? ("not_found" as const) : defect(cause),
807
958
  * );
808
959
  *
809
- * user.unwrap(); // => the fetched user (on success)
810
- * // when fetchUser rejects with NotFoundError: => Err("not_found")
960
+ * if (user.isOk()) user.value; // => the fetched user
961
+ * // when fetchUser rejects with NotFoundError: user is Err("not_found")
811
962
  * ```
812
963
  */
813
964
  function fromPromise(promise, qualify) {
@@ -821,7 +972,8 @@ function fromPromise(promise, qualify) {
821
972
  * @remarks
822
973
  * Use this only when a rejection genuinely indicates a bug rather than an
823
974
  * anticipated outcome — the error channel is `never`, so there is nothing to
824
- * triage. (`await`-ing still yields a `Result`; it never throws.)
975
+ * triage. (`await`-ing still yields a `Result`; it never throws.) The
976
+ * synchronous counterpart is {@link fromSafeThrowable}.
825
977
  *
826
978
  * @typeParam T - the resolved value type.
827
979
  * @param promise - the promise, or a thunk returning one.
@@ -832,7 +984,7 @@ function fromPromise(promise, qualify) {
832
984
  * ```ts
833
985
  * import { fromSafePromise } from "unthrown";
834
986
  *
835
- * (await fromSafePromise(Promise.resolve(3))).unwrap(); // => 3
987
+ * (await fromSafePromise(Promise.resolve(3))).get(); // => 3
836
988
  * // a rejection becomes a Defect (never a modeled Err):
837
989
  * await fromSafePromise(Promise.reject(new Error("boom"))); // => Defect(Error("boom"))
838
990
  * ```
@@ -906,7 +1058,7 @@ function foldRecord(results) {
906
1058
  * ```ts
907
1059
  * import { all, Ok, Err } from "unthrown";
908
1060
  *
909
- * all([Ok(1), Ok("a"), Ok(true)]).unwrap(); // => [1, "a", true] (typed [number, string, boolean])
1061
+ * all([Ok(1), Ok("a"), Ok(true)]).get(); // => [1, "a", true] (typed [number, string, boolean])
910
1062
  * all([Ok(1), Err("e"), Ok(3)]); // => Err("e") (short-circuits on the first Err)
911
1063
  * ```
912
1064
  */
@@ -929,7 +1081,7 @@ function all(results) {
929
1081
  * ```ts
930
1082
  * import { allFromDict, Ok, Err } from "unthrown";
931
1083
  *
932
- * allFromDict({ id: Ok(1), name: Ok("ada") }).unwrap(); // => { id: 1, name: "ada" }
1084
+ * allFromDict({ id: Ok(1), name: Ok("ada") }).get(); // => { id: 1, name: "ada" }
933
1085
  * allFromDict({ id: Ok(1), name: Err("missing") }); // => Err("missing")
934
1086
  * ```
935
1087
  */
@@ -953,7 +1105,7 @@ function allFromDict(results) {
953
1105
  * import { allAsync, fromSafePromise } from "unthrown";
954
1106
  *
955
1107
  * const both = allAsync([fromSafePromise(Promise.resolve(1)), fromSafePromise(Promise.resolve(2))]);
956
- * (await both).unwrap(); // => [1, 2]
1108
+ * (await both).get(); // => [1, 2]
957
1109
  * ```
958
1110
  */
959
1111
  function allAsync(results) {
@@ -977,7 +1129,7 @@ function allAsync(results) {
977
1129
  * a: fromSafePromise(Promise.resolve(1)),
978
1130
  * b: fromSafePromise(Promise.resolve("x")),
979
1131
  * });
980
- * (await both).unwrap(); // => { a: 1, b: "x" }
1132
+ * (await both).get(); // => { a: 1, b: "x" }
981
1133
  * ```
982
1134
  */
983
1135
  function allFromDictAsync(results) {
@@ -996,8 +1148,9 @@ function allFromDictAsync(results) {
996
1148
  * Companion object grouping the **`Result`-producing** entry points under a
997
1149
  * single, discoverable namespace: {@link Result.Ok}, {@link Result.Err},
998
1150
  * {@link Result.Do}, {@link Result.fromNullable}, {@link Result.fromThrowable},
999
- * {@link Result.all}, {@link Result.allFromDict}, {@link Result.isOk},
1000
- * {@link Result.isErr}, {@link Result.isDefect}, {@link Result.isResult}.
1151
+ * {@link Result.fromSafeThrowable}, {@link Result.all},
1152
+ * {@link Result.allFromDict}, {@link Result.isOk}, {@link Result.isErr},
1153
+ * {@link Result.isDefect}, {@link Result.isResult}.
1001
1154
  *
1002
1155
  * @remarks
1003
1156
  * Purely additive sugar — each member **is** the corresponding free function.
@@ -1014,7 +1167,7 @@ function allFromDictAsync(results) {
1014
1167
  * @example
1015
1168
  * ```ts
1016
1169
  * import { Result } from "unthrown";
1017
- * Result.Ok(1).flatMap((n) => Result.Ok(n + 1)).unwrap(); // => 2
1170
+ * Result.Ok(1).flatMap((n) => Result.Ok(n + 1)).get(); // => 2
1018
1171
  * ```
1019
1172
  */
1020
1173
  const Result = {
@@ -1023,6 +1176,7 @@ const Result = {
1023
1176
  Do,
1024
1177
  fromNullable,
1025
1178
  fromThrowable,
1179
+ fromSafeThrowable,
1026
1180
  all,
1027
1181
  allFromDict,
1028
1182
  isOk,
@@ -1032,18 +1186,20 @@ const Result = {
1032
1186
  };
1033
1187
  /**
1034
1188
  * Companion object grouping the **`AsyncResult`-producing** entry points under
1035
- * the matching namespace: {@link AsyncResult.fromPromise},
1036
- * {@link AsyncResult.fromSafePromise}, {@link AsyncResult.all},
1037
- * {@link AsyncResult.allFromDict}.
1189
+ * the matching namespace: {@link AsyncResult.Ok}, {@link AsyncResult.Err},
1190
+ * {@link AsyncResult.fromPromise}, {@link AsyncResult.fromSafePromise},
1191
+ * {@link AsyncResult.all}, {@link AsyncResult.allFromDict}.
1038
1192
  *
1039
1193
  * @remarks
1040
1194
  * The async sibling of {@link Result}. Statics are grouped by what they
1041
- * **return**, so `fromPromise`/`fromSafePromise` and the async aggregates sit
1042
- * here rather than on {@link Result}; the namespace already conveys "async", so
1043
- * the aggregates drop the `Async` suffix (`AsyncResult.all` is the free function
1044
- * `allAsync`; `AsyncResult.allFromDict` is `allFromDictAsync`). Like
1045
- * {@link Result}, the free functions remain the primary, tree-shakeable API; the
1046
- * value `AsyncResult` and the type {@link AsyncResult} share one name.
1195
+ * **return**, so the pre-lifted constructors, `fromPromise`/`fromSafePromise`,
1196
+ * and the async aggregates sit here rather than on {@link Result}; the namespace
1197
+ * already conveys "async", so the members drop the `Async` suffix their free
1198
+ * functions carry (`AsyncResult.Ok` is `OkAsync`; `AsyncResult.Err` is
1199
+ * `ErrAsync`; `AsyncResult.all` is `allAsync`; `AsyncResult.allFromDict` is
1200
+ * `allFromDictAsync`). Like {@link Result}, the free functions remain the
1201
+ * primary, tree-shakeable API; the value `AsyncResult` and the type
1202
+ * {@link AsyncResult} share one name.
1047
1203
  *
1048
1204
  * @category Facade
1049
1205
  *
@@ -1051,10 +1207,12 @@ const Result = {
1051
1207
  * ```ts
1052
1208
  * import { AsyncResult } from "unthrown";
1053
1209
  * const user = await AsyncResult.fromPromise(fetchUser(id), (c, defect) => defect(c));
1054
- * user.unwrap(); // => the fetched user (on success)
1210
+ * user.get(); // => the fetched user (on success)
1055
1211
  * ```
1056
1212
  */
1057
1213
  const AsyncResult = {
1214
+ Ok: OkAsync,
1215
+ Err: ErrAsync,
1058
1216
  fromPromise,
1059
1217
  fromSafePromise,
1060
1218
  all: allAsync,
@@ -1068,8 +1226,13 @@ const AsyncResult = {
1068
1226
  *
1069
1227
  * @remarks
1070
1228
  * Extend the returned class to declare a concrete error. Supply the payload with
1071
- * an instantiation expression; omit it for a payload-less error. A `message`
1072
- * field in the payload is forwarded to `Error`. The `_tag` always reflects
1229
+ * an instantiation expression; omit it for a payload-less error. The `message`
1230
+ * is **not** a payload field — it is the human string owned by `Error`, not
1231
+ * structured data, so it is reserved. Define it once per subclass the standard
1232
+ * way, `override message = "…"` (it may interpolate the payload via `this`,
1233
+ * which the base populates before the subclass field initialiser runs); a
1234
+ * payload `message` is rejected at compile time, so contextual detail lives in
1235
+ * typed fields, never baked into per-call prose. The `_tag` always reflects
1073
1236
  * `tag` and cannot be overridden by the payload. `name` is likewise reserved —
1074
1237
  * it is the display label (set it with `options.name`); a payload `name` is
1075
1238
  * rejected at compile time (and excluded from the instance type), so it can't
@@ -1084,11 +1247,14 @@ const AsyncResult = {
1084
1247
  * ```ts
1085
1248
  * class RetryableError extends TaggedError("@my-lib/RetryableError", {
1086
1249
  * name: "RetryableError",
1087
- * })<{ message: string }> {}
1088
- *
1089
- * const e = new RetryableError({ message: "boom" });
1090
- * e._tag; // "@my-lib/RetryableError" — namespaced discriminant
1091
- * e.name; // "RetryableError" — clean display name
1250
+ * }) {
1251
+ * override message = "operation failed; safe to retry";
1252
+ * }
1253
+ *
1254
+ * const e = new RetryableError();
1255
+ * e._tag; // "@my-lib/RetryableError" — namespaced discriminant
1256
+ * e.name; // "RetryableError" — clean display name
1257
+ * e.message; // "operation failed; safe to retry" — the standard Error.message
1092
1258
  * ```
1093
1259
  *
1094
1260
  * @typeParam Tag - the string literal discriminant.
@@ -1112,10 +1278,11 @@ function TaggedError(tag, options) {
1112
1278
  class TaggedErrorBase extends Error {
1113
1279
  _tag;
1114
1280
  constructor(props) {
1115
- super(typeof props?.["message"] === "string" ? props["message"] : void 0);
1281
+ super();
1116
1282
  if (props) Object.assign(this, props);
1117
1283
  this._tag = tag;
1118
1284
  this.name = displayName;
1285
+ delete this.message;
1119
1286
  Object.setPrototypeOf(this, new.target.prototype);
1120
1287
  }
1121
1288
  }
@@ -1137,7 +1304,9 @@ function matchTags(result, handlers) {
1137
1304
  exports.AsyncResult = AsyncResult;
1138
1305
  exports.Do = Do;
1139
1306
  exports.Err = Err;
1307
+ exports.ErrAsync = ErrAsync;
1140
1308
  exports.Ok = Ok;
1309
+ exports.OkAsync = OkAsync;
1141
1310
  exports.Result = Result;
1142
1311
  exports.TaggedError = TaggedError;
1143
1312
  exports.UnwrapError = UnwrapError;
@@ -1148,6 +1317,7 @@ exports.allFromDictAsync = allFromDictAsync;
1148
1317
  exports.fromNullable = fromNullable;
1149
1318
  exports.fromPromise = fromPromise;
1150
1319
  exports.fromSafePromise = fromSafePromise;
1320
+ exports.fromSafeThrowable = fromSafeThrowable;
1151
1321
  exports.fromThrowable = fromThrowable;
1152
1322
  exports.isDefect = isDefect;
1153
1323
  exports.isErr = isErr;