effect 3.12.11 → 3.13.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.
Files changed (204) hide show
  1. package/README.md +38 -49
  2. package/dist/cjs/Channel.js.map +1 -1
  3. package/dist/cjs/DateTime.js +17 -1
  4. package/dist/cjs/DateTime.js.map +1 -1
  5. package/dist/cjs/Differ.js.map +1 -1
  6. package/dist/cjs/Duration.js +128 -1
  7. package/dist/cjs/Duration.js.map +1 -1
  8. package/dist/cjs/Effect.js +175 -37
  9. package/dist/cjs/Effect.js.map +1 -1
  10. package/dist/cjs/Either.js +2 -1
  11. package/dist/cjs/Either.js.map +1 -1
  12. package/dist/cjs/FiberHandle.js +54 -21
  13. package/dist/cjs/FiberHandle.js.map +1 -1
  14. package/dist/cjs/FiberMap.js +51 -24
  15. package/dist/cjs/FiberMap.js.map +1 -1
  16. package/dist/cjs/FiberSet.js +50 -17
  17. package/dist/cjs/FiberSet.js.map +1 -1
  18. package/dist/cjs/HashMap.js +19 -1
  19. package/dist/cjs/HashMap.js.map +1 -1
  20. package/dist/cjs/HashSet.js +9 -1
  21. package/dist/cjs/HashSet.js.map +1 -1
  22. package/dist/cjs/Layer.js +21 -1
  23. package/dist/cjs/Layer.js.map +1 -1
  24. package/dist/cjs/Match.js +659 -38
  25. package/dist/cjs/Match.js.map +1 -1
  26. package/dist/cjs/RcMap.js +11 -1
  27. package/dist/cjs/RcMap.js.map +1 -1
  28. package/dist/cjs/Reloadable.js.map +1 -1
  29. package/dist/cjs/STM.js.map +1 -1
  30. package/dist/cjs/Schedule.js +1074 -309
  31. package/dist/cjs/Schedule.js.map +1 -1
  32. package/dist/cjs/Schema.js +73 -1
  33. package/dist/cjs/Schema.js.map +1 -1
  34. package/dist/cjs/Stream.js.map +1 -1
  35. package/dist/cjs/internal/channel.js.map +1 -1
  36. package/dist/cjs/internal/core-effect.js.map +1 -1
  37. package/dist/cjs/internal/core.js +27 -3
  38. package/dist/cjs/internal/core.js.map +1 -1
  39. package/dist/cjs/internal/dateTime.js +4 -1
  40. package/dist/cjs/internal/dateTime.js.map +1 -1
  41. package/dist/cjs/internal/differ.js +4 -0
  42. package/dist/cjs/internal/differ.js.map +1 -1
  43. package/dist/cjs/internal/effect/circular.js +3 -2
  44. package/dist/cjs/internal/effect/circular.js.map +1 -1
  45. package/dist/cjs/internal/fiberRuntime.js +21 -7
  46. package/dist/cjs/internal/fiberRuntime.js.map +1 -1
  47. package/dist/cjs/internal/hashMap.js +10 -1
  48. package/dist/cjs/internal/hashMap.js.map +1 -1
  49. package/dist/cjs/internal/keyedPool.js +1 -1
  50. package/dist/cjs/internal/keyedPool.js.map +1 -1
  51. package/dist/cjs/internal/layer.js.map +1 -1
  52. package/dist/cjs/internal/rcMap.js +86 -56
  53. package/dist/cjs/internal/rcMap.js.map +1 -1
  54. package/dist/cjs/internal/reloadable.js.map +1 -1
  55. package/dist/cjs/internal/schedule.js.map +1 -1
  56. package/dist/cjs/internal/sink.js.map +1 -1
  57. package/dist/cjs/internal/stm/stm.js.map +1 -1
  58. package/dist/cjs/internal/stream.js.map +1 -1
  59. package/dist/cjs/internal/version.js +1 -1
  60. package/dist/cjs/internal/version.js.map +1 -1
  61. package/dist/dts/Channel.d.ts +4 -4
  62. package/dist/dts/Channel.d.ts.map +1 -1
  63. package/dist/dts/DateTime.d.ts +16 -0
  64. package/dist/dts/DateTime.d.ts.map +1 -1
  65. package/dist/dts/Differ.d.ts +2 -1
  66. package/dist/dts/Differ.d.ts.map +1 -1
  67. package/dist/dts/Duration.d.ts +64 -0
  68. package/dist/dts/Duration.d.ts.map +1 -1
  69. package/dist/dts/Effect.d.ts +402 -30
  70. package/dist/dts/Effect.d.ts.map +1 -1
  71. package/dist/dts/Either.d.ts +7 -0
  72. package/dist/dts/Either.d.ts.map +1 -1
  73. package/dist/dts/FiberHandle.d.ts +26 -0
  74. package/dist/dts/FiberHandle.d.ts.map +1 -1
  75. package/dist/dts/FiberMap.d.ts +26 -0
  76. package/dist/dts/FiberMap.d.ts.map +1 -1
  77. package/dist/dts/FiberSet.d.ts +25 -0
  78. package/dist/dts/FiberSet.d.ts.map +1 -1
  79. package/dist/dts/HashMap.d.ts +38 -0
  80. package/dist/dts/HashMap.d.ts.map +1 -1
  81. package/dist/dts/HashSet.d.ts +7 -0
  82. package/dist/dts/HashSet.d.ts.map +1 -1
  83. package/dist/dts/Layer.d.ts +32 -13
  84. package/dist/dts/Layer.d.ts.map +1 -1
  85. package/dist/dts/Match.d.ts +731 -48
  86. package/dist/dts/Match.d.ts.map +1 -1
  87. package/dist/dts/RcMap.d.ts +32 -0
  88. package/dist/dts/RcMap.d.ts.map +1 -1
  89. package/dist/dts/Reloadable.d.ts +13 -13
  90. package/dist/dts/Reloadable.d.ts.map +1 -1
  91. package/dist/dts/STM.d.ts +4 -4
  92. package/dist/dts/STM.d.ts.map +1 -1
  93. package/dist/dts/Schedule.d.ts +2294 -633
  94. package/dist/dts/Schedule.d.ts.map +1 -1
  95. package/dist/dts/Schema.d.ts +40 -4
  96. package/dist/dts/Schema.d.ts.map +1 -1
  97. package/dist/dts/Stream.d.ts +8 -8
  98. package/dist/dts/Stream.d.ts.map +1 -1
  99. package/dist/dts/Trie.d.ts +7 -7
  100. package/dist/dts/Trie.d.ts.map +1 -1
  101. package/dist/dts/index.d.ts +25 -0
  102. package/dist/dts/index.d.ts.map +1 -1
  103. package/dist/dts/internal/stm/stm.d.ts +2 -2
  104. package/dist/dts/internal/stm/stm.d.ts.map +1 -1
  105. package/dist/esm/Channel.js.map +1 -1
  106. package/dist/esm/DateTime.js +16 -0
  107. package/dist/esm/DateTime.js.map +1 -1
  108. package/dist/esm/Differ.js.map +1 -1
  109. package/dist/esm/Duration.js +124 -0
  110. package/dist/esm/Duration.js.map +1 -1
  111. package/dist/esm/Effect.js +170 -32
  112. package/dist/esm/Effect.js.map +1 -1
  113. package/dist/esm/Either.js +7 -0
  114. package/dist/esm/Either.js.map +1 -1
  115. package/dist/esm/FiberHandle.js +48 -18
  116. package/dist/esm/FiberHandle.js.map +1 -1
  117. package/dist/esm/FiberMap.js +46 -22
  118. package/dist/esm/FiberMap.js.map +1 -1
  119. package/dist/esm/FiberSet.js +45 -15
  120. package/dist/esm/FiberSet.js.map +1 -1
  121. package/dist/esm/HashMap.js +17 -0
  122. package/dist/esm/HashMap.js.map +1 -1
  123. package/dist/esm/HashSet.js +7 -0
  124. package/dist/esm/HashSet.js.map +1 -1
  125. package/dist/esm/Layer.js +20 -0
  126. package/dist/esm/Layer.js.map +1 -1
  127. package/dist/esm/Match.js +665 -40
  128. package/dist/esm/Match.js.map +1 -1
  129. package/dist/esm/RcMap.js +10 -0
  130. package/dist/esm/RcMap.js.map +1 -1
  131. package/dist/esm/Reloadable.js.map +1 -1
  132. package/dist/esm/STM.js.map +1 -1
  133. package/dist/esm/Schedule.js +1074 -309
  134. package/dist/esm/Schedule.js.map +1 -1
  135. package/dist/esm/Schema.js +71 -0
  136. package/dist/esm/Schema.js.map +1 -1
  137. package/dist/esm/Stream.js.map +1 -1
  138. package/dist/esm/index.js +25 -0
  139. package/dist/esm/index.js.map +1 -1
  140. package/dist/esm/internal/channel.js.map +1 -1
  141. package/dist/esm/internal/core-effect.js.map +1 -1
  142. package/dist/esm/internal/core.js +23 -0
  143. package/dist/esm/internal/core.js.map +1 -1
  144. package/dist/esm/internal/dateTime.js +2 -0
  145. package/dist/esm/internal/dateTime.js.map +1 -1
  146. package/dist/esm/internal/differ.js +4 -0
  147. package/dist/esm/internal/differ.js.map +1 -1
  148. package/dist/esm/internal/effect/circular.js +3 -2
  149. package/dist/esm/internal/effect/circular.js.map +1 -1
  150. package/dist/esm/internal/fiberRuntime.js +18 -5
  151. package/dist/esm/internal/fiberRuntime.js.map +1 -1
  152. package/dist/esm/internal/hashMap.js +9 -0
  153. package/dist/esm/internal/hashMap.js.map +1 -1
  154. package/dist/esm/internal/keyedPool.js +1 -1
  155. package/dist/esm/internal/keyedPool.js.map +1 -1
  156. package/dist/esm/internal/layer.js.map +1 -1
  157. package/dist/esm/internal/rcMap.js +85 -55
  158. package/dist/esm/internal/rcMap.js.map +1 -1
  159. package/dist/esm/internal/reloadable.js.map +1 -1
  160. package/dist/esm/internal/schedule.js.map +1 -1
  161. package/dist/esm/internal/sink.js.map +1 -1
  162. package/dist/esm/internal/stm/stm.js.map +1 -1
  163. package/dist/esm/internal/stream.js.map +1 -1
  164. package/dist/esm/internal/version.js +1 -1
  165. package/dist/esm/internal/version.js.map +1 -1
  166. package/package.json +2 -1
  167. package/src/Channel.ts +14 -17
  168. package/src/DateTime.ts +17 -8
  169. package/src/Differ.ts +2 -1
  170. package/src/Duration.ts +147 -0
  171. package/src/Effect.ts +528 -140
  172. package/src/Either.ts +9 -0
  173. package/src/FiberHandle.ts +95 -35
  174. package/src/FiberMap.ts +104 -39
  175. package/src/FiberSet.ts +93 -24
  176. package/src/HashMap.ts +40 -0
  177. package/src/HashSet.ts +8 -0
  178. package/src/Layer.ts +94 -40
  179. package/src/Match.ts +733 -49
  180. package/src/RcMap.ts +34 -0
  181. package/src/Reloadable.ts +17 -27
  182. package/src/STM.ts +10 -17
  183. package/src/Schedule.ts +2325 -653
  184. package/src/Schema.ts +81 -4
  185. package/src/Stream.ts +26 -33
  186. package/src/Trie.ts +7 -7
  187. package/src/index.ts +25 -0
  188. package/src/internal/channel.ts +37 -39
  189. package/src/internal/core-effect.ts +84 -84
  190. package/src/internal/core.ts +80 -0
  191. package/src/internal/dateTime.ts +3 -0
  192. package/src/internal/differ.ts +4 -0
  193. package/src/internal/effect/circular.ts +3 -2
  194. package/src/internal/fiberRuntime.ts +31 -6
  195. package/src/internal/hashMap.ts +16 -0
  196. package/src/internal/keyedPool.ts +1 -1
  197. package/src/internal/layer.ts +52 -52
  198. package/src/internal/rcMap.ts +131 -89
  199. package/src/internal/reloadable.ts +25 -28
  200. package/src/internal/schedule.ts +29 -23
  201. package/src/internal/sink.ts +16 -15
  202. package/src/internal/stm/stm.ts +54 -46
  203. package/src/internal/stream.ts +100 -100
  204. package/src/internal/version.ts +1 -1
package/src/Match.ts CHANGED
@@ -1,4 +1,29 @@
1
1
  /**
2
+ * The `effect/match` module provides a type-safe pattern matching system for
3
+ * TypeScript. Inspired by functional programming, it simplifies conditional
4
+ * logic by replacing verbose if/else or switch statements with a structured and
5
+ * expressive API.
6
+ *
7
+ * This module supports matching against types, values, and discriminated unions
8
+ * while enforcing exhaustiveness checking to ensure all cases are handled.
9
+ *
10
+ * Although pattern matching is not yet a native JavaScript feature,
11
+ * `effect/match` offers a reliable implementation that is available today.
12
+ *
13
+ * **How Pattern Matching Works**
14
+ *
15
+ * Pattern matching follows a structured process:
16
+ *
17
+ * - **Creating a matcher**: Define a `Matcher` that operates on either a
18
+ * specific `Match.type` or `Match.value`.
19
+ *
20
+ * - **Defining patterns**: Use combinators such as `Match.when`, `Match.not`,
21
+ * and `Match.tag` to specify matching conditions.
22
+ *
23
+ * - **Completing the match**: Apply a finalizer such as `Match.exhaustive`,
24
+ * `Match.orElse`, or `Match.option` to determine how unmatched cases should
25
+ * be handled.
26
+ *
2
27
  * @since 1.0.0
3
28
  */
4
29
  import type * as Either from "./Either.js"
@@ -10,19 +35,53 @@ import type * as T from "./Types.js"
10
35
  import type { Unify } from "./Unify.js"
11
36
 
12
37
  /**
13
- * @category type ids
38
+ * @category Symbols
14
39
  * @since 1.0.0
15
40
  */
16
41
  export const MatcherTypeId: unique symbol = internal.TypeId
17
42
 
18
43
  /**
19
- * @category type ids
44
+ * @category Symbols
20
45
  * @since 1.0.0
21
46
  */
22
47
  export type MatcherTypeId = typeof MatcherTypeId
23
48
 
24
49
  /**
25
- * @category model
50
+ * Pattern matching follows a structured process:
51
+ *
52
+ * - **Creating a matcher**: Define a `Matcher` that operates on either a
53
+ * specific `Match.type` or `Match.value`.
54
+ *
55
+ * - **Defining patterns**: Use combinators such as `Match.when`, `Match.not`,
56
+ * and `Match.tag` to specify matching conditions.
57
+ *
58
+ * - **Completing the match**: Apply a finalizer such as `Match.exhaustive`,
59
+ * `Match.orElse`, or `Match.option` to determine how unmatched cases should
60
+ * be handled.
61
+ *
62
+ * @example
63
+ * ```ts
64
+ * import { Match } from "effect"
65
+ *
66
+ * // Simulated dynamic input that can be a string or a number
67
+ * const input: string | number = "some input"
68
+ *
69
+ * // ┌─── string
70
+ * // ▼
71
+ * const result = Match.value(input).pipe(
72
+ * // Match if the value is a number
73
+ * Match.when(Match.number, (n) => `number: ${n}`),
74
+ * // Match if the value is a string
75
+ * Match.when(Match.string, (s) => `string: ${s}`),
76
+ * // Ensure all possible cases are covered
77
+ * Match.exhaustive
78
+ * )
79
+ *
80
+ * console.log(result)
81
+ * // Output: "string: some input"
82
+ * ```
83
+ *
84
+ * @category Model
26
85
  * @since 1.0.0
27
86
  */
28
87
  export type Matcher<Input, Filters, RemainingApplied, Result, Provided, Return = any> =
@@ -30,7 +89,7 @@ export type Matcher<Input, Filters, RemainingApplied, Result, Provided, Return =
30
89
  | ValueMatcher<Input, Filters, RemainingApplied, Result, Provided, Return>
31
90
 
32
91
  /**
33
- * @category model
92
+ * @category Model
34
93
  * @since 1.0.0
35
94
  */
36
95
  export interface TypeMatcher<in Input, out Filters, out Remaining, out Result, out Return = any> extends Pipeable {
@@ -47,7 +106,7 @@ export interface TypeMatcher<in Input, out Filters, out Remaining, out Result, o
47
106
  }
48
107
 
49
108
  /**
50
- * @category model
109
+ * @category Model
51
110
  * @since 1.0.0
52
111
  */
53
112
  export interface ValueMatcher<in Input, Filters, out Remaining, out Result, Provided, out Return = any>
@@ -66,13 +125,13 @@ export interface ValueMatcher<in Input, Filters, out Remaining, out Result, Prov
66
125
  }
67
126
 
68
127
  /**
69
- * @category model
128
+ * @category Model
70
129
  * @since 1.0.0
71
130
  */
72
131
  export type Case = When | Not
73
132
 
74
133
  /**
75
- * @category model
134
+ * @category Model
76
135
  * @since 1.0.0
77
136
  */
78
137
  export interface When {
@@ -82,7 +141,7 @@ export interface When {
82
141
  }
83
142
 
84
143
  /**
85
- * @category model
144
+ * @category Model
86
145
  * @since 1.0.0
87
146
  */
88
147
  export interface Not {
@@ -92,13 +151,85 @@ export interface Not {
92
151
  }
93
152
 
94
153
  /**
95
- * @category constructors
154
+ * Creates a matcher for a specific type.
155
+ *
156
+ * **Details**
157
+ *
158
+ * This function defines a `Matcher` that operates on a given type, allowing you
159
+ * to specify conditions for handling different cases. Once the matcher is
160
+ * created, you can use pattern-matching functions like {@link when} to define
161
+ * how different values should be processed.
162
+ *
163
+ * @see {@link value} for creating a matcher from a specific value.
164
+ *
165
+ * @example
166
+ * ```ts
167
+ * // Title: Matching Numbers and Strings
168
+ * import { Match } from "effect"
169
+ *
170
+ * // Create a matcher for values that are either strings or numbers
171
+ * //
172
+ * // ┌─── (u: string | number) => string
173
+ * // ▼
174
+ * const match = Match.type<string | number>().pipe(
175
+ * // Match when the value is a number
176
+ * Match.when(Match.number, (n) => `number: ${n}`),
177
+ * // Match when the value is a string
178
+ * Match.when(Match.string, (s) => `string: ${s}`),
179
+ * // Ensure all possible cases are handled
180
+ * Match.exhaustive
181
+ * )
182
+ *
183
+ * console.log(match(0))
184
+ * // Output: "number: 0"
185
+ *
186
+ * console.log(match("hello"))
187
+ * // Output: "string: hello"
188
+ * ```
189
+ *
190
+ * @category Creating a matcher
96
191
  * @since 1.0.0
97
192
  */
98
193
  export const type: <I>() => Matcher<I, Types.Without<never>, I, never, never> = internal.type
99
194
 
100
195
  /**
101
- * @category constructors
196
+ * Creates a matcher from a specific value.
197
+ *
198
+ * **Details**
199
+ *
200
+ * This function allows you to define a `Matcher` directly from a given value,
201
+ * rather than from a type. This is useful when working with known values,
202
+ * enabling structured pattern matching on objects, primitives, or any data
203
+ * structure.
204
+ *
205
+ * Once the matcher is created, you can use pattern-matching functions like
206
+ * {@link when} to define how different cases should be handled.
207
+ *
208
+ * @see {@link type} for creating a matcher from a specific type.
209
+ *
210
+ * @example
211
+ * ```ts
212
+ * // Title: Matching an Object by Property
213
+ * import { Match } from "effect"
214
+ *
215
+ * const input = { name: "John", age: 30 }
216
+ *
217
+ * // Create a matcher for the specific object
218
+ * const result = Match.value(input).pipe(
219
+ * // Match when the 'name' property is "John"
220
+ * Match.when(
221
+ * { name: "John" },
222
+ * (user) => `${user.name} is ${user.age} years old`
223
+ * ),
224
+ * // Provide a fallback if no match is found
225
+ * Match.orElse(() => "Oh, not John")
226
+ * )
227
+ *
228
+ * console.log(result)
229
+ * // Output: "John is 30 years old"
230
+ * ```
231
+ *
232
+ * @category Creating a matcher
102
233
  * @since 1.0.0
103
234
  */
104
235
  export const value: <const I>(
@@ -106,7 +237,7 @@ export const value: <const I>(
106
237
  ) => Matcher<I, Types.Without<never>, I, never, I> = internal.value
107
238
 
108
239
  /**
109
- * @category constructors
240
+ * @category Creating a matcher
110
241
  * @since 1.0.0
111
242
  */
112
243
  export const valueTags: <
@@ -121,7 +252,7 @@ export const valueTags: <
121
252
  >(fields: P) => (input: I) => Unify<ReturnType<P[keyof P]>> = internal.valueTags
122
253
 
123
254
  /**
124
- * @category constructors
255
+ * @category Creating a matcher
125
256
  * @since 1.0.0
126
257
  */
127
258
  export const typeTags: <I>() => <
@@ -135,7 +266,34 @@ export const typeTags: <I>() => <
135
266
  >(fields: P) => (input: I) => Unify<ReturnType<P[keyof P]>> = internal.typeTags
136
267
 
137
268
  /**
138
- * @category combinators
269
+ * Ensures that all branches of a matcher return a specific type.
270
+ *
271
+ * **Details**
272
+ *
273
+ * This function enforces a consistent return type across all pattern-matching
274
+ * branches. By specifying a return type, TypeScript will check that every
275
+ * matching condition produces a value of the expected type.
276
+ *
277
+ * **Important:** This function must be the first step in the matcher pipeline.
278
+ * If used later, TypeScript will not enforce type consistency correctly.
279
+ *
280
+ * @example
281
+ * ```ts
282
+ * // Title: Validating Return Type Consistency
283
+ * import { Match } from "effect"
284
+ *
285
+ * const match = Match.type<{ a: number } | { b: string }>().pipe(
286
+ * // Ensure all branches return a string
287
+ * Match.withReturnType<string>(),
288
+ * // ❌ Type error: 'number' is not assignable to type 'string'
289
+ * // @ts-expect-error
290
+ * Match.when({ a: Match.number }, (_) => _.a),
291
+ * // ✅ Correct: returns a string
292
+ * Match.when({ b: Match.string }, (_) => _.b),
293
+ * Match.exhaustive
294
+ * )
295
+ * ```
296
+ *
139
297
  * @since 1.0.0
140
298
  */
141
299
  export const withReturnType: <Ret>() => <I, F, R, A, Pr, _>(
@@ -144,7 +302,50 @@ export const withReturnType: <Ret>() => <I, F, R, A, Pr, _>(
144
302
  : "withReturnType constraint does not extend Result type" = internal.withReturnType
145
303
 
146
304
  /**
147
- * @category combinators
305
+ * Defines a condition for matching values.
306
+ *
307
+ * **Details**
308
+ *
309
+ * This function enables pattern matching by checking whether a given value
310
+ * satisfies a condition. It supports both direct value comparisons and
311
+ * predicate functions. If the condition is met, the associated function is
312
+ * executed.
313
+ *
314
+ * This function is useful when defining matchers that need to check for
315
+ * specific values or apply logical conditions to determine a match. It works
316
+ * well with structured objects and primitive types.
317
+ *
318
+ * @see {@link whenOr} Use this when multiple patterns should match in a single
319
+ * condition.
320
+ * @see {@link whenAnd} Use this when a value must match all provided patterns.
321
+ * @see {@link orElse} Provides a fallback when no patterns match.
322
+ *
323
+ * @example
324
+ * ```ts
325
+ * // Title: Matching with Values and Predicates
326
+ * import { Match } from "effect"
327
+ *
328
+ * // Create a matcher for objects with an "age" property
329
+ * const match = Match.type<{ age: number }>().pipe(
330
+ * // Match when age is greater than 18
331
+ * Match.when({ age: (age) => age > 18 }, (user) => `Age: ${user.age}`),
332
+ * // Match when age is exactly 18
333
+ * Match.when({ age: 18 }, () => "You can vote"),
334
+ * // Fallback case for all other ages
335
+ * Match.orElse((user) => `${user.age} is too young`)
336
+ * )
337
+ *
338
+ * console.log(match({ age: 20 }))
339
+ * // Output: "Age: 20"
340
+ *
341
+ * console.log(match({ age: 18 }))
342
+ * // Output: "You can vote"
343
+ *
344
+ * console.log(match({ age: 4 }))
345
+ * // Output: "4 is too young"
346
+ * ```
347
+ *
348
+ * @category Defining patterns
148
349
  * @since 1.0.0
149
350
  */
150
351
  export const when: <
@@ -167,7 +368,45 @@ export const when: <
167
368
  > = internal.when
168
369
 
169
370
  /**
170
- * @category combinators
371
+ * Matches one of multiple patterns in a single condition.
372
+ *
373
+ * **Details**
374
+ *
375
+ * This function allows defining a condition where a value matches any of the
376
+ * provided patterns. If a match is found, the associated function is executed.
377
+ * It simplifies cases where multiple patterns share the same handling logic.
378
+ *
379
+ * Unlike {@link when}, which requires separate conditions for each pattern,
380
+ * this function enables combining them into a single statement, making the
381
+ * matcher more concise.
382
+ *
383
+ * @example
384
+ * ```ts
385
+ * import { Match } from "effect"
386
+ *
387
+ * type ErrorType =
388
+ * | { readonly _tag: "NetworkError"; readonly message: string }
389
+ * | { readonly _tag: "TimeoutError"; readonly duration: number }
390
+ * | { readonly _tag: "ValidationError"; readonly field: string }
391
+ *
392
+ * const handleError = Match.type<ErrorType>().pipe(
393
+ * Match.whenOr(
394
+ * { _tag: "NetworkError" },
395
+ * { _tag: "TimeoutError" },
396
+ * () => "Retry the request"
397
+ * ),
398
+ * Match.when({ _tag: "ValidationError" }, (_) => `Invalid field: ${_.field}`),
399
+ * Match.exhaustive
400
+ * )
401
+ *
402
+ * console.log(handleError({ _tag: "NetworkError", message: "No connection" }))
403
+ * // Output: "Retry the request"
404
+ *
405
+ * console.log(handleError({ _tag: "ValidationError", field: "email" }))
406
+ * // Output: "Invalid field: email"
407
+ * ```
408
+ *
409
+ * @category Defining patterns
171
410
  * @since 1.0.0
172
411
  */
173
412
  export const whenOr: <
@@ -189,7 +428,42 @@ export const whenOr: <
189
428
  > = internal.whenOr
190
429
 
191
430
  /**
192
- * @category combinators
431
+ * Matches a value that satisfies all provided patterns.
432
+ *
433
+ * **Details**
434
+ *
435
+ * This function allows defining a condition where a value must match all the
436
+ * given patterns simultaneously. If the value satisfies every pattern, the
437
+ * associated function is executed.
438
+ *
439
+ * Unlike {@link when}, which matches a single pattern at a time, this function
440
+ * ensures that multiple conditions are met before executing the callback. It is
441
+ * useful when checking for values that need to fulfill multiple criteria at
442
+ * once.
443
+ *
444
+ * @example
445
+ * ```ts
446
+ * import { Match } from "effect"
447
+ *
448
+ * type User = { readonly age: number; readonly role: "admin" | "user" }
449
+ *
450
+ * const checkUser = Match.type<User>().pipe(
451
+ * Match.whenAnd(
452
+ * { age: (n) => n >= 18 },
453
+ * { role: "admin" },
454
+ * () => "Admin access granted"
455
+ * ),
456
+ * Match.orElse(() => "Access denied")
457
+ * )
458
+ *
459
+ * console.log(checkUser({ age: 20, role: "admin" }))
460
+ * // Output: "Admin access granted"
461
+ *
462
+ * console.log(checkUser({ age: 20, role: "user" }))
463
+ * // Output: "Access denied"
464
+ * ```
465
+ *
466
+ * @category Defining patterns
193
467
  * @since 1.0.0
194
468
  */
195
469
  export const whenAnd: <
@@ -210,7 +484,29 @@ export const whenAnd: <
210
484
  > = internal.whenAnd
211
485
 
212
486
  /**
213
- * @category combinators
487
+ * Matches values based on a specified discriminant field.
488
+ *
489
+ * **Details**
490
+ *
491
+ * This function is used to define pattern matching on objects that follow a
492
+ * **discriminated union** structure, where a specific field (e.g., `type`,
493
+ * `kind`, `_tag`) determines the variant of the object. It allows matching
494
+ * multiple values of the discriminant and provides a function to handle the
495
+ * matched cases.
496
+ *
497
+ * @example
498
+ * ```ts
499
+ * import { Match, pipe } from "effect"
500
+ *
501
+ * const match = pipe(
502
+ * Match.type<{ type: "A"; a: string } | { type: "B"; b: number } | { type: "C"; c: boolean }>(),
503
+ * Match.discriminator("type")("A", "B", (_) => `A or B: ${_.type}`),
504
+ * Match.discriminator("type")("C", (_) => `C(${_.c})`),
505
+ * Match.exhaustive
506
+ * )
507
+ * ```
508
+ *
509
+ * @category Defining patterns
214
510
  * @since 1.0.0
215
511
  */
216
512
  export const discriminator: <D extends string>(
@@ -229,7 +525,37 @@ export const discriminator: <D extends string>(
229
525
  > = internal.discriminator
230
526
 
231
527
  /**
232
- * @category combinators
528
+ * Matches values where a specified field starts with a given prefix.
529
+ *
530
+ * **Details**
531
+ *
532
+ * This function is useful for working with discriminated unions where the
533
+ * discriminant field follows a hierarchical or namespaced structure. It allows
534
+ * you to match values based on whether the specified field starts with a given
535
+ * prefix, making it easier to handle grouped cases.
536
+ *
537
+ * Instead of checking for exact matches, this function lets you match values
538
+ * that share a common prefix. For example, if your discriminant field contains
539
+ * hierarchical names like `"A"`, `"A.A"`, and `"B"`, you can match all values
540
+ * starting with `"A"` using a single rule.
541
+ *
542
+ * @example
543
+ * ```ts
544
+ * import { Match, pipe } from "effect"
545
+ *
546
+ * const match = pipe(
547
+ * Match.type<{ type: "A" } | { type: "B" } | { type: "A.A" } | {}>(),
548
+ * Match.discriminatorStartsWith("type")("A", (_) => 1 as const),
549
+ * Match.discriminatorStartsWith("type")("B", (_) => 2 as const),
550
+ * Match.orElse((_) => 3 as const)
551
+ * )
552
+ *
553
+ * console.log(match({ type: "A" })) // 1
554
+ * console.log(match({ type: "B" })) // 2
555
+ * console.log(match({ type: "A.A" })) // 1
556
+ * ```
557
+ *
558
+ * @category Defining patterns
233
559
  * @since 1.0.0
234
560
  */
235
561
  export const discriminatorStartsWith: <D extends string>(
@@ -249,7 +575,34 @@ export const discriminatorStartsWith: <D extends string>(
249
575
  > = internal.discriminatorStartsWith as any
250
576
 
251
577
  /**
252
- * @category combinators
578
+ * Matches values based on a field that serves as a discriminator, mapping each
579
+ * possible value to a corresponding handler.
580
+ *
581
+ * **Details**
582
+ *
583
+ * This function simplifies working with discriminated unions by letting you
584
+ * define a set of handlers for each possible value of a given field. Instead of
585
+ * chaining multiple calls to {@link discriminator}, this function allows
586
+ * defining all possible cases at once using an object where the keys are the
587
+ * possible values of the field, and the values are the corresponding handler
588
+ * functions.
589
+ *
590
+ * @example
591
+ * ```ts
592
+ * import { Match, pipe } from "effect"
593
+ *
594
+ * const match = pipe(
595
+ * Match.type<{ type: "A"; a: string } | { type: "B"; b: number } | { type: "C"; c: boolean }>(),
596
+ * Match.discriminators("type")({
597
+ * A: (a) => a.a,
598
+ * B: (b) => b.b,
599
+ * C: (c) => c.c
600
+ * }),
601
+ * Match.exhaustive
602
+ * )
603
+ * ```
604
+ *
605
+ * @category Defining patterns
253
606
  * @since 1.0.0
254
607
  */
255
608
  export const discriminators: <D extends string>(
@@ -274,7 +627,35 @@ export const discriminators: <D extends string>(
274
627
  > = internal.discriminators
275
628
 
276
629
  /**
277
- * @category combinators
630
+ * Matches values based on a discriminator field and **ensures all cases are
631
+ * handled**.
632
+ *
633
+ * **Details*+
634
+ *
635
+ * This function is similar to {@link discriminators}, but **requires that all
636
+ * possible cases** are explicitly handled. It is useful when working with
637
+ * discriminated unions, where a specific field (e.g., `"type"`) determines the
638
+ * shape of an object. Each possible value of the field must have a
639
+ * corresponding handler, ensuring **exhaustiveness checking** at compile time.
640
+ *
641
+ * This function **does not require** `Match.exhaustive` at the end of the
642
+ * pipeline because it enforces exhaustiveness by design.
643
+ *
644
+ * @example
645
+ * ```ts
646
+ * import { Match, pipe } from "effect"
647
+ *
648
+ * const match = pipe(
649
+ * Match.type<{ type: "A"; a: string } | { type: "B"; b: number } | { type: "C"; c: boolean }>(),
650
+ * Match.discriminatorsExhaustive("type")({
651
+ * A: (a) => a.a,
652
+ * B: (b) => b.b,
653
+ * C: (c) => c.c
654
+ * })
655
+ * )
656
+ * ```
657
+ *
658
+ * @category Defining patterns
278
659
  * @since 1.0.0
279
660
  */
280
661
  export const discriminatorsExhaustive: <D extends string>(
@@ -293,7 +674,46 @@ export const discriminatorsExhaustive: <D extends string>(
293
674
  internal.discriminatorsExhaustive
294
675
 
295
676
  /**
296
- * @category combinators
677
+ * The `Match.tag` function allows pattern matching based on the `_tag` field in
678
+ * a [Discriminated Union](https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes-func.html#discriminated-unions).
679
+ * You can specify multiple tags to match within a single pattern.
680
+ *
681
+ * **Note**
682
+ *
683
+ * The `Match.tag` function relies on the convention within the Effect ecosystem
684
+ * of naming the tag field as `"_tag"`. Ensure that your discriminated unions
685
+ * follow this naming convention for proper functionality.
686
+ *
687
+ * @example
688
+ * ```ts
689
+ * // Title: Matching a Discriminated Union by Tag
690
+ * import { Match } from "effect"
691
+ *
692
+ * type Event =
693
+ * | { readonly _tag: "fetch" }
694
+ * | { readonly _tag: "success"; readonly data: string }
695
+ * | { readonly _tag: "error"; readonly error: Error }
696
+ * | { readonly _tag: "cancel" }
697
+ *
698
+ * // Create a Matcher for Either<number, string>
699
+ * const match = Match.type<Event>().pipe(
700
+ * // Match either "fetch" or "success"
701
+ * Match.tag("fetch", "success", () => `Ok!`),
702
+ * // Match "error" and extract the error message
703
+ * Match.tag("error", (event) => `Error: ${event.error.message}`),
704
+ * // Match "cancel"
705
+ * Match.tag("cancel", () => "Cancelled"),
706
+ * Match.exhaustive
707
+ * )
708
+ *
709
+ * console.log(match({ _tag: "success", data: "Hello" }))
710
+ * // Output: "Ok!"
711
+ *
712
+ * console.log(match({ _tag: "error", error: new Error("Oops!") }))
713
+ * // Output: "Error: Oops!"
714
+ * ```
715
+ *
716
+ * @category Defining patterns
297
717
  * @since 1.0.0
298
718
  */
299
719
  export const tag: <R, P extends Types.Tags<"_tag", R> & string, Ret, B extends Ret>(
@@ -310,7 +730,32 @@ export const tag: <R, P extends Types.Tags<"_tag", R> & string, Ret, B extends R
310
730
  > = internal.tag
311
731
 
312
732
  /**
313
- * @category combinators
733
+ * Matches values where the `_tag` field starts with a given prefix.
734
+ *
735
+ * **Details**
736
+ *
737
+ * This function allows you to match on values in a **discriminated union**
738
+ * based on whether the `_tag` field starts with a specified prefix. It is
739
+ * useful for handling hierarchical or namespaced tags, where multiple related
740
+ * cases share a common prefix.
741
+ *
742
+ * @example
743
+ * ```ts
744
+ * import { Match, pipe } from "effect"
745
+ *
746
+ * const match = pipe(
747
+ * Match.type<{ _tag: "A" } | { _tag: "B" } | { _tag: "A.A" } | {}>(),
748
+ * Match.tagStartsWith("A", (_) => 1 as const),
749
+ * Match.tagStartsWith("B", (_) => 2 as const),
750
+ * Match.orElse((_) => 3 as const)
751
+ * )
752
+ *
753
+ * console.log(match({ _tag: "A" })) // 1
754
+ * console.log(match({ _tag: "B" })) // 2
755
+ * console.log(match({ _tag: "A.A" })) // 1
756
+ * ```
757
+ *
758
+ * @category Defining patterns
314
759
  * @since 1.0.0
315
760
  */
316
761
  export const tagStartsWith: <R, P extends string, Ret, B extends Ret>(
@@ -325,10 +770,35 @@ export const tagStartsWith: <R, P extends string, Ret, B extends Ret>(
325
770
  B | A,
326
771
  Pr,
327
772
  Ret
328
- > = internal.tagStartsWith as any
773
+ > = internal.tagStartsWith
329
774
 
330
775
  /**
331
- * @category combinators
776
+ * Matches values based on their `_tag` field, mapping each tag to a
777
+ * corresponding handler.
778
+ *
779
+ * **Details**
780
+ *
781
+ * This function provides a way to handle discriminated unions by mapping `_tag`
782
+ * values to specific functions. Each handler receives the matched value and
783
+ * returns a transformed result. If all possible tags are handled, you can
784
+ * enforce exhaustiveness using `Match.exhaustive` to ensure no case is missed.
785
+ *
786
+ * @example
787
+ * ```ts
788
+ * import { Match, pipe } from "effect"
789
+ *
790
+ * const match = pipe(
791
+ * Match.type<{ _tag: "A"; a: string } | { _tag: "B"; b: number } | { _tag: "C"; c: boolean }>(),
792
+ * Match.tags({
793
+ * A: (a) => a.a,
794
+ * B: (b) => b.b,
795
+ * C: (c) => c.c
796
+ * }),
797
+ * Match.exhaustive
798
+ * )
799
+ * ```
800
+ *
801
+ * @category Defining patterns
332
802
  * @since 1.0.0
333
803
  */
334
804
  export const tags: <
@@ -351,7 +821,32 @@ export const tags: <
351
821
  > = internal.tags
352
822
 
353
823
  /**
354
- * @category combinators
824
+ * Matches values based on their `_tag` field and requires handling of all
825
+ * possible cases.
826
+ *
827
+ * **Details**
828
+ *
829
+ * This function is designed for **discriminated unions** where every possible
830
+ * `_tag` value must have a corresponding handler. Unlike {@link tags}, this
831
+ * function ensures **exhaustiveness**, meaning all cases must be explicitly
832
+ * handled. If a `_tag` value is missing from the mapping, TypeScript will
833
+ * report an error.
834
+ *
835
+ * @example
836
+ * ```ts
837
+ * import { Match, pipe } from "effect"
838
+ *
839
+ * const match = pipe(
840
+ * Match.type<{ _tag: "A"; a: string } | { _tag: "B"; b: number } | { _tag: "C"; c: boolean }>(),
841
+ * Match.tagsExhaustive({
842
+ * A: (a) => a.a,
843
+ * B: (b) => b.b,
844
+ * C: (c) => c.c
845
+ * })
846
+ * )
847
+ * ```
848
+ *
849
+ * @category Defining patterns
355
850
  * @since 1.0.0
356
851
  */
357
852
  export const tagsExhaustive: <
@@ -368,7 +863,37 @@ export const tagsExhaustive: <
368
863
  internal.tagsExhaustive
369
864
 
370
865
  /**
371
- * @category combinators
866
+ * Excludes a specific value from matching while allowing all others.
867
+ *
868
+ * **Details**
869
+ *
870
+ * This function is useful when you need to **handle all values except one or
871
+ * more specific cases**. Instead of listing all possible matches manually, this
872
+ * function simplifies the logic by allowing you to specify values to exclude.
873
+ * Any excluded value will bypass the provided function and continue matching
874
+ * through other cases.
875
+ *
876
+ * @example
877
+ * ```ts
878
+ * // Title: Ignoring a Specific Value
879
+ * import { Match } from "effect"
880
+ *
881
+ * // Create a matcher for string or number values
882
+ * const match = Match.type<string | number>().pipe(
883
+ * // Match any value except "hi", returning "ok"
884
+ * Match.not("hi", () => "ok"),
885
+ * // Fallback case for when the value is "hi"
886
+ * Match.orElse(() => "fallback")
887
+ * )
888
+ *
889
+ * console.log(match("hello"))
890
+ * // Output: "ok"
891
+ *
892
+ * console.log(match("hi"))
893
+ * // Output: "fallback"
894
+ * ```
895
+ *
896
+ * @category Defining patterns
372
897
  * @since 1.0.0
373
898
  */
374
899
  export const not: <
@@ -391,13 +916,17 @@ export const not: <
391
916
  > = internal.not
392
917
 
393
918
  /**
394
- * @category predicates
919
+ * Matches non-empty strings.
920
+ *
921
+ * @category Predicates
395
922
  * @since 1.0.0
396
923
  */
397
924
  export const nonEmptyString: SafeRefinement<string, never> = internal.nonEmptyString
398
925
 
399
926
  /**
400
- * @category predicates
927
+ * Matches a specific set of literal values (e.g., `Match.is("a", 42, true)`).
928
+ *
929
+ * @category Predicates
401
930
  * @since 1.0.0
402
931
  */
403
932
  export const is: <
@@ -405,31 +934,41 @@ export const is: <
405
934
  >(...literals: Literals) => Predicate.Refinement<unknown, Literals[number]> = internal.is
406
935
 
407
936
  /**
408
- * @category predicates
937
+ * Matches values of type `string`.
938
+ *
939
+ * @category Predicates
409
940
  * @since 1.0.0
410
941
  */
411
942
  export const string: Predicate.Refinement<unknown, string> = Predicate.isString
412
943
 
413
944
  /**
414
- * @category predicates
945
+ * Matches values of type `number`.
946
+ *
947
+ * @category Predicates
415
948
  * @since 1.0.0
416
949
  */
417
950
  export const number: Predicate.Refinement<unknown, number> = Predicate.isNumber
418
951
 
419
952
  /**
420
- * @category predicates
953
+ * Matches any value without restrictions.
954
+ *
955
+ * @category Predicates
421
956
  * @since 1.0.0
422
957
  */
423
958
  export const any: SafeRefinement<unknown, any> = internal.any
424
959
 
425
960
  /**
426
- * @category predicates
961
+ * Matches any defined (non-null and non-undefined) value.
962
+ *
963
+ * @category Predicates
427
964
  * @since 1.0.0
428
965
  */
429
966
  export const defined: <A>(u: A) => u is A & {} = internal.defined
430
967
 
431
968
  /**
432
- * @category predicates
969
+ * Matches values of type `boolean`.
970
+ *
971
+ * @category Predicates
433
972
  * @since 1.0.0
434
973
  */
435
974
  export const boolean: Predicate.Refinement<unknown, boolean> = Predicate.isBoolean
@@ -437,7 +976,9 @@ export const boolean: Predicate.Refinement<unknown, boolean> = Predicate.isBoole
437
976
  const _undefined: Predicate.Refinement<unknown, undefined> = Predicate.isUndefined
438
977
  export {
439
978
  /**
440
- * @category predicates
979
+ * Matches the value `undefined`.
980
+ *
981
+ * @category Predicates
441
982
  * @since 1.0.0
442
983
  */
443
984
  _undefined as undefined
@@ -446,38 +987,50 @@ export {
446
987
  const _null: Predicate.Refinement<unknown, null> = Predicate.isNull
447
988
  export {
448
989
  /**
449
- * @category predicates
990
+ * Matches the value `null`.
991
+ *
992
+ * @category Predicates
450
993
  * @since 1.0.0
451
994
  */
452
995
  _null as null
453
996
  }
454
997
 
455
998
  /**
456
- * @category predicates
999
+ * Matches values of type `bigint`.
1000
+ *
1001
+ * @category Predicates
457
1002
  * @since 1.0.0
458
1003
  */
459
1004
  export const bigint: Predicate.Refinement<unknown, bigint> = Predicate.isBigInt
460
1005
 
461
1006
  /**
462
- * @category predicates
1007
+ * Matches values of type `symbol`.
1008
+ *
1009
+ * @category Predicates
463
1010
  * @since 1.0.0
464
1011
  */
465
1012
  export const symbol: Predicate.Refinement<unknown, symbol> = Predicate.isSymbol
466
1013
 
467
1014
  /**
468
- * @category predicates
1015
+ * Matches values that are instances of `Date`.
1016
+ *
1017
+ * @category Predicates
469
1018
  * @since 1.0.0
470
1019
  */
471
1020
  export const date: Predicate.Refinement<unknown, Date> = Predicate.isDate
472
1021
 
473
1022
  /**
474
- * @category predicates
1023
+ * Matches objects where keys are `string` or `symbol` and values are `unknown`.
1024
+ *
1025
+ * @category Predicates
475
1026
  * @since 1.0.0
476
1027
  */
477
1028
  export const record: Predicate.Refinement<unknown, { [x: string | symbol]: unknown }> = Predicate.isRecord
478
1029
 
479
1030
  /**
480
- * @category predicates
1031
+ * Matches instances of a given class.
1032
+ *
1033
+ * @category Predicates
481
1034
  * @since 1.0.0
482
1035
  */
483
1036
  export const instanceOf: <A extends abstract new(...args: any) => any>(
@@ -485,7 +1038,7 @@ export const instanceOf: <A extends abstract new(...args: any) => any>(
485
1038
  ) => SafeRefinement<InstanceType<A>, never> = internal.instanceOf
486
1039
 
487
1040
  /**
488
- * @category predicates
1041
+ * @category Predicates
489
1042
  * @since 1.0.0
490
1043
  */
491
1044
  export const instanceOfUnsafe: <A extends abstract new(...args: any) => any>(
@@ -493,7 +1046,36 @@ export const instanceOfUnsafe: <A extends abstract new(...args: any) => any>(
493
1046
  ) => SafeRefinement<InstanceType<A>, InstanceType<A>> = internal.instanceOf
494
1047
 
495
1048
  /**
496
- * @category conversions
1049
+ * Provides a fallback value when no patterns match.
1050
+ *
1051
+ * **Details**
1052
+ *
1053
+ * This function ensures that a matcher always returns a valid result, even if
1054
+ * no defined patterns match. It acts as a default case, similar to the
1055
+ * `default` clause in a `switch` statement or the final `else` in an `if-else`
1056
+ * chain.
1057
+ *
1058
+ * @example
1059
+ * ```ts
1060
+ * // Title: Providing a Default Value When No Patterns Match
1061
+ * import { Match } from "effect"
1062
+ *
1063
+ * // Create a matcher for string or number values
1064
+ * const match = Match.type<string | number>().pipe(
1065
+ * // Match when the value is "a"
1066
+ * Match.when("a", () => "ok"),
1067
+ * // Fallback when no patterns match
1068
+ * Match.orElse(() => "fallback")
1069
+ * )
1070
+ *
1071
+ * console.log(match("a"))
1072
+ * // Output: "ok"
1073
+ *
1074
+ * console.log(match("b"))
1075
+ * // Output: "fallback"
1076
+ * ```
1077
+ *
1078
+ * @category Completion
497
1079
  * @since 1.0.0
498
1080
  */
499
1081
  export const orElse: <RA, Ret, F extends (_: RA) => Ret>(
@@ -502,8 +1084,21 @@ export const orElse: <RA, Ret, F extends (_: RA) => Ret>(
502
1084
  self: Matcher<I, R, RA, A, Pr, Ret>
503
1085
  ) => [Pr] extends [never] ? (input: I) => Unify<ReturnType<F> | A> : Unify<ReturnType<F> | A> = internal.orElse
504
1086
 
1087
+ // TODO(4.0): Rename to "orThrow"? Like Either.getOrThrow
505
1088
  /**
506
- * @category conversions
1089
+ * Throws an error if no pattern matches.
1090
+ *
1091
+ * **Details**
1092
+ *
1093
+ * This function finalizes a matcher by ensuring that if no patterns match, an
1094
+ * error is thrown. It is useful when all cases should be covered, and any
1095
+ * unexpected input should trigger an error instead of returning a default
1096
+ * value.
1097
+ *
1098
+ * When used, this function removes the need for an explicit fallback case and
1099
+ * ensures that an unmatched value is never silently ignored.
1100
+ *
1101
+ * @category Completion
507
1102
  * @since 1.0.0
508
1103
  */
509
1104
  export const orElseAbsurd: <I, R, RA, A, Pr, Ret>(
@@ -511,7 +1106,42 @@ export const orElseAbsurd: <I, R, RA, A, Pr, Ret>(
511
1106
  ) => [Pr] extends [never] ? (input: I) => Unify<A> : Unify<A> = internal.orElseAbsurd
512
1107
 
513
1108
  /**
514
- * @category conversions
1109
+ * Wraps the match result in an `Either`, distinguishing matched and unmatched
1110
+ * cases.
1111
+ *
1112
+ * **Details**
1113
+ *
1114
+ * This function ensures that the result of a matcher is always wrapped in an
1115
+ * `Either`, allowing clear differentiation between successful matches
1116
+ * (`Right(value)`) and cases where no pattern matched (`Left(unmatched
1117
+ * value)`).
1118
+ *
1119
+ * This approach is particularly useful when handling optional values or when an
1120
+ * unmatched case should be explicitly handled rather than returning a default
1121
+ * value or throwing an error.
1122
+ *
1123
+ * @example
1124
+ * ```ts
1125
+ * // Title: Extracting a User Role with Either
1126
+ * import { Match } from "effect"
1127
+ *
1128
+ * type User = { readonly role: "admin" | "editor" | "viewer" }
1129
+ *
1130
+ * // Create a matcher to extract user roles
1131
+ * const getRole = Match.type<User>().pipe(
1132
+ * Match.when({ role: "admin" }, () => "Has full access"),
1133
+ * Match.when({ role: "editor" }, () => "Can edit content"),
1134
+ * Match.either // Wrap the result in an Either
1135
+ * )
1136
+ *
1137
+ * console.log(getRole({ role: "admin" }))
1138
+ * // Output: { _id: 'Either', _tag: 'Right', right: 'Has full access' }
1139
+ *
1140
+ * console.log(getRole({ role: "viewer" }))
1141
+ * // Output: { _id: 'Either', _tag: 'Left', left: { role: 'viewer' } }
1142
+ * ```
1143
+ *
1144
+ * @category Completion
515
1145
  * @since 1.0.0
516
1146
  */
517
1147
  export const either: <I, F, R, A, Pr, Ret>(
@@ -519,7 +1149,40 @@ export const either: <I, F, R, A, Pr, Ret>(
519
1149
  ) => [Pr] extends [never] ? (input: I) => Either.Either<Unify<A>, R> : Either.Either<Unify<A>, R> = internal.either
520
1150
 
521
1151
  /**
522
- * @category conversions
1152
+ * Wraps the match result in an `Option`, representing an optional match.
1153
+ *
1154
+ * **Details**
1155
+ *
1156
+ * This function ensures that the result of a matcher is wrapped in an `Option`,
1157
+ * making it easy to handle cases where no pattern matches. If a match is found,
1158
+ * it returns `Some(value)`, otherwise, it returns `None`.
1159
+ *
1160
+ * This is useful in cases where a missing match is expected and should be
1161
+ * handled explicitly rather than throwing an error or returning a default
1162
+ * value.
1163
+ *
1164
+ * @example
1165
+ * ```ts
1166
+ * // Title: Extracting a User Role with Option
1167
+ * import { Match } from "effect"
1168
+ *
1169
+ * type User = { readonly role: "admin" | "editor" | "viewer" }
1170
+ *
1171
+ * // Create a matcher to extract user roles
1172
+ * const getRole = Match.type<User>().pipe(
1173
+ * Match.when({ role: "admin" }, () => "Has full access"),
1174
+ * Match.when({ role: "editor" }, () => "Can edit content"),
1175
+ * Match.option // Wrap the result in an Option
1176
+ * )
1177
+ *
1178
+ * console.log(getRole({ role: "admin" }))
1179
+ * // Output: { _id: 'Option', _tag: 'Some', value: 'Has full access' }
1180
+ *
1181
+ * console.log(getRole({ role: "viewer" }))
1182
+ * // Output: { _id: 'Option', _tag: 'None' }
1183
+ * ```
1184
+ *
1185
+ * @category Completion
523
1186
  * @since 1.0.0
524
1187
  */
525
1188
  export const option: <I, F, R, A, Pr, Ret>(
@@ -527,7 +1190,28 @@ export const option: <I, F, R, A, Pr, Ret>(
527
1190
  ) => [Pr] extends [never] ? (input: I) => Option.Option<Unify<A>> : Option.Option<Unify<A>> = internal.option
528
1191
 
529
1192
  /**
530
- * @category conversions
1193
+ * The `Match.exhaustive` method finalizes the pattern matching process by
1194
+ * ensuring that all possible cases are accounted for. If any case is missing,
1195
+ * TypeScript will produce a type error. This is particularly useful when
1196
+ * working with unions, as it helps prevent unintended gaps in pattern matching.
1197
+ *
1198
+ * @example
1199
+ * ```ts
1200
+ * // Title: Ensuring All Cases Are Covered
1201
+ * import { Match } from "effect"
1202
+ *
1203
+ * // Create a matcher for string or number values
1204
+ * const match = Match.type<string | number>().pipe(
1205
+ * // Match when the value is a number
1206
+ * Match.when(Match.number, (n) => `number: ${n}`),
1207
+ * // Mark the match as exhaustive, ensuring all cases are handled
1208
+ * // TypeScript will throw an error if any case is missing
1209
+ * // @ts-expect-error Type 'string' is not assignable to type 'never'
1210
+ * Match.exhaustive
1211
+ * )
1212
+ * ```
1213
+ *
1214
+ * @category Completion
531
1215
  * @since 1.0.0
532
1216
  */
533
1217
  export const exhaustive: <I, F, A, Pr, Ret>(
@@ -536,18 +1220,18 @@ export const exhaustive: <I, F, A, Pr, Ret>(
536
1220
 
537
1221
  /**
538
1222
  * @since 1.0.0
539
- * @category type ids
1223
+ * @category Symbols
540
1224
  */
541
1225
  export const SafeRefinementId = Symbol.for("effect/SafeRefinement")
542
1226
 
543
1227
  /**
544
1228
  * @since 1.0.0
545
- * @category type ids
1229
+ * @category Symbols
546
1230
  */
547
1231
  export type SafeRefinementId = typeof SafeRefinementId
548
1232
 
549
1233
  /**
550
- * @category model
1234
+ * @category Model
551
1235
  * @since 1.0.0
552
1236
  */
553
1237
  export interface SafeRefinement<in A, out R = A> {