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/dist/esm/Match.js CHANGED
@@ -1,202 +1,827 @@
1
1
  import * as internal from "./internal/matcher.js";
2
2
  import * as Predicate from "./Predicate.js";
3
3
  /**
4
- * @category type ids
4
+ * @category Symbols
5
5
  * @since 1.0.0
6
6
  */
7
7
  export const MatcherTypeId = internal.TypeId;
8
8
  /**
9
- * @category constructors
9
+ * Creates a matcher for a specific type.
10
+ *
11
+ * **Details**
12
+ *
13
+ * This function defines a `Matcher` that operates on a given type, allowing you
14
+ * to specify conditions for handling different cases. Once the matcher is
15
+ * created, you can use pattern-matching functions like {@link when} to define
16
+ * how different values should be processed.
17
+ *
18
+ * @see {@link value} for creating a matcher from a specific value.
19
+ *
20
+ * @example
21
+ * ```ts
22
+ * // Title: Matching Numbers and Strings
23
+ * import { Match } from "effect"
24
+ *
25
+ * // Create a matcher for values that are either strings or numbers
26
+ * //
27
+ * // ┌─── (u: string | number) => string
28
+ * // ▼
29
+ * const match = Match.type<string | number>().pipe(
30
+ * // Match when the value is a number
31
+ * Match.when(Match.number, (n) => `number: ${n}`),
32
+ * // Match when the value is a string
33
+ * Match.when(Match.string, (s) => `string: ${s}`),
34
+ * // Ensure all possible cases are handled
35
+ * Match.exhaustive
36
+ * )
37
+ *
38
+ * console.log(match(0))
39
+ * // Output: "number: 0"
40
+ *
41
+ * console.log(match("hello"))
42
+ * // Output: "string: hello"
43
+ * ```
44
+ *
45
+ * @category Creating a matcher
10
46
  * @since 1.0.0
11
47
  */
12
48
  export const type = internal.type;
13
49
  /**
14
- * @category constructors
50
+ * Creates a matcher from a specific value.
51
+ *
52
+ * **Details**
53
+ *
54
+ * This function allows you to define a `Matcher` directly from a given value,
55
+ * rather than from a type. This is useful when working with known values,
56
+ * enabling structured pattern matching on objects, primitives, or any data
57
+ * structure.
58
+ *
59
+ * Once the matcher is created, you can use pattern-matching functions like
60
+ * {@link when} to define how different cases should be handled.
61
+ *
62
+ * @see {@link type} for creating a matcher from a specific type.
63
+ *
64
+ * @example
65
+ * ```ts
66
+ * // Title: Matching an Object by Property
67
+ * import { Match } from "effect"
68
+ *
69
+ * const input = { name: "John", age: 30 }
70
+ *
71
+ * // Create a matcher for the specific object
72
+ * const result = Match.value(input).pipe(
73
+ * // Match when the 'name' property is "John"
74
+ * Match.when(
75
+ * { name: "John" },
76
+ * (user) => `${user.name} is ${user.age} years old`
77
+ * ),
78
+ * // Provide a fallback if no match is found
79
+ * Match.orElse(() => "Oh, not John")
80
+ * )
81
+ *
82
+ * console.log(result)
83
+ * // Output: "John is 30 years old"
84
+ * ```
85
+ *
86
+ * @category Creating a matcher
15
87
  * @since 1.0.0
16
88
  */
17
89
  export const value = internal.value;
18
90
  /**
19
- * @category constructors
91
+ * @category Creating a matcher
20
92
  * @since 1.0.0
21
93
  */
22
94
  export const valueTags = internal.valueTags;
23
95
  /**
24
- * @category constructors
96
+ * @category Creating a matcher
25
97
  * @since 1.0.0
26
98
  */
27
99
  export const typeTags = internal.typeTags;
28
100
  /**
29
- * @category combinators
101
+ * Ensures that all branches of a matcher return a specific type.
102
+ *
103
+ * **Details**
104
+ *
105
+ * This function enforces a consistent return type across all pattern-matching
106
+ * branches. By specifying a return type, TypeScript will check that every
107
+ * matching condition produces a value of the expected type.
108
+ *
109
+ * **Important:** This function must be the first step in the matcher pipeline.
110
+ * If used later, TypeScript will not enforce type consistency correctly.
111
+ *
112
+ * @example
113
+ * ```ts
114
+ * // Title: Validating Return Type Consistency
115
+ * import { Match } from "effect"
116
+ *
117
+ * const match = Match.type<{ a: number } | { b: string }>().pipe(
118
+ * // Ensure all branches return a string
119
+ * Match.withReturnType<string>(),
120
+ * // ❌ Type error: 'number' is not assignable to type 'string'
121
+ * // @ts-expect-error
122
+ * Match.when({ a: Match.number }, (_) => _.a),
123
+ * // ✅ Correct: returns a string
124
+ * Match.when({ b: Match.string }, (_) => _.b),
125
+ * Match.exhaustive
126
+ * )
127
+ * ```
128
+ *
30
129
  * @since 1.0.0
31
130
  */
32
131
  export const withReturnType = internal.withReturnType;
33
132
  /**
34
- * @category combinators
133
+ * Defines a condition for matching values.
134
+ *
135
+ * **Details**
136
+ *
137
+ * This function enables pattern matching by checking whether a given value
138
+ * satisfies a condition. It supports both direct value comparisons and
139
+ * predicate functions. If the condition is met, the associated function is
140
+ * executed.
141
+ *
142
+ * This function is useful when defining matchers that need to check for
143
+ * specific values or apply logical conditions to determine a match. It works
144
+ * well with structured objects and primitive types.
145
+ *
146
+ * @see {@link whenOr} Use this when multiple patterns should match in a single
147
+ * condition.
148
+ * @see {@link whenAnd} Use this when a value must match all provided patterns.
149
+ * @see {@link orElse} Provides a fallback when no patterns match.
150
+ *
151
+ * @example
152
+ * ```ts
153
+ * // Title: Matching with Values and Predicates
154
+ * import { Match } from "effect"
155
+ *
156
+ * // Create a matcher for objects with an "age" property
157
+ * const match = Match.type<{ age: number }>().pipe(
158
+ * // Match when age is greater than 18
159
+ * Match.when({ age: (age) => age > 18 }, (user) => `Age: ${user.age}`),
160
+ * // Match when age is exactly 18
161
+ * Match.when({ age: 18 }, () => "You can vote"),
162
+ * // Fallback case for all other ages
163
+ * Match.orElse((user) => `${user.age} is too young`)
164
+ * )
165
+ *
166
+ * console.log(match({ age: 20 }))
167
+ * // Output: "Age: 20"
168
+ *
169
+ * console.log(match({ age: 18 }))
170
+ * // Output: "You can vote"
171
+ *
172
+ * console.log(match({ age: 4 }))
173
+ * // Output: "4 is too young"
174
+ * ```
175
+ *
176
+ * @category Defining patterns
35
177
  * @since 1.0.0
36
178
  */
37
179
  export const when = internal.when;
38
180
  /**
39
- * @category combinators
181
+ * Matches one of multiple patterns in a single condition.
182
+ *
183
+ * **Details**
184
+ *
185
+ * This function allows defining a condition where a value matches any of the
186
+ * provided patterns. If a match is found, the associated function is executed.
187
+ * It simplifies cases where multiple patterns share the same handling logic.
188
+ *
189
+ * Unlike {@link when}, which requires separate conditions for each pattern,
190
+ * this function enables combining them into a single statement, making the
191
+ * matcher more concise.
192
+ *
193
+ * @example
194
+ * ```ts
195
+ * import { Match } from "effect"
196
+ *
197
+ * type ErrorType =
198
+ * | { readonly _tag: "NetworkError"; readonly message: string }
199
+ * | { readonly _tag: "TimeoutError"; readonly duration: number }
200
+ * | { readonly _tag: "ValidationError"; readonly field: string }
201
+ *
202
+ * const handleError = Match.type<ErrorType>().pipe(
203
+ * Match.whenOr(
204
+ * { _tag: "NetworkError" },
205
+ * { _tag: "TimeoutError" },
206
+ * () => "Retry the request"
207
+ * ),
208
+ * Match.when({ _tag: "ValidationError" }, (_) => `Invalid field: ${_.field}`),
209
+ * Match.exhaustive
210
+ * )
211
+ *
212
+ * console.log(handleError({ _tag: "NetworkError", message: "No connection" }))
213
+ * // Output: "Retry the request"
214
+ *
215
+ * console.log(handleError({ _tag: "ValidationError", field: "email" }))
216
+ * // Output: "Invalid field: email"
217
+ * ```
218
+ *
219
+ * @category Defining patterns
40
220
  * @since 1.0.0
41
221
  */
42
222
  export const whenOr = internal.whenOr;
43
223
  /**
44
- * @category combinators
224
+ * Matches a value that satisfies all provided patterns.
225
+ *
226
+ * **Details**
227
+ *
228
+ * This function allows defining a condition where a value must match all the
229
+ * given patterns simultaneously. If the value satisfies every pattern, the
230
+ * associated function is executed.
231
+ *
232
+ * Unlike {@link when}, which matches a single pattern at a time, this function
233
+ * ensures that multiple conditions are met before executing the callback. It is
234
+ * useful when checking for values that need to fulfill multiple criteria at
235
+ * once.
236
+ *
237
+ * @example
238
+ * ```ts
239
+ * import { Match } from "effect"
240
+ *
241
+ * type User = { readonly age: number; readonly role: "admin" | "user" }
242
+ *
243
+ * const checkUser = Match.type<User>().pipe(
244
+ * Match.whenAnd(
245
+ * { age: (n) => n >= 18 },
246
+ * { role: "admin" },
247
+ * () => "Admin access granted"
248
+ * ),
249
+ * Match.orElse(() => "Access denied")
250
+ * )
251
+ *
252
+ * console.log(checkUser({ age: 20, role: "admin" }))
253
+ * // Output: "Admin access granted"
254
+ *
255
+ * console.log(checkUser({ age: 20, role: "user" }))
256
+ * // Output: "Access denied"
257
+ * ```
258
+ *
259
+ * @category Defining patterns
45
260
  * @since 1.0.0
46
261
  */
47
262
  export const whenAnd = internal.whenAnd;
48
263
  /**
49
- * @category combinators
264
+ * Matches values based on a specified discriminant field.
265
+ *
266
+ * **Details**
267
+ *
268
+ * This function is used to define pattern matching on objects that follow a
269
+ * **discriminated union** structure, where a specific field (e.g., `type`,
270
+ * `kind`, `_tag`) determines the variant of the object. It allows matching
271
+ * multiple values of the discriminant and provides a function to handle the
272
+ * matched cases.
273
+ *
274
+ * @example
275
+ * ```ts
276
+ * import { Match, pipe } from "effect"
277
+ *
278
+ * const match = pipe(
279
+ * Match.type<{ type: "A"; a: string } | { type: "B"; b: number } | { type: "C"; c: boolean }>(),
280
+ * Match.discriminator("type")("A", "B", (_) => `A or B: ${_.type}`),
281
+ * Match.discriminator("type")("C", (_) => `C(${_.c})`),
282
+ * Match.exhaustive
283
+ * )
284
+ * ```
285
+ *
286
+ * @category Defining patterns
50
287
  * @since 1.0.0
51
288
  */
52
289
  export const discriminator = internal.discriminator;
53
290
  /**
54
- * @category combinators
291
+ * Matches values where a specified field starts with a given prefix.
292
+ *
293
+ * **Details**
294
+ *
295
+ * This function is useful for working with discriminated unions where the
296
+ * discriminant field follows a hierarchical or namespaced structure. It allows
297
+ * you to match values based on whether the specified field starts with a given
298
+ * prefix, making it easier to handle grouped cases.
299
+ *
300
+ * Instead of checking for exact matches, this function lets you match values
301
+ * that share a common prefix. For example, if your discriminant field contains
302
+ * hierarchical names like `"A"`, `"A.A"`, and `"B"`, you can match all values
303
+ * starting with `"A"` using a single rule.
304
+ *
305
+ * @example
306
+ * ```ts
307
+ * import { Match, pipe } from "effect"
308
+ *
309
+ * const match = pipe(
310
+ * Match.type<{ type: "A" } | { type: "B" } | { type: "A.A" } | {}>(),
311
+ * Match.discriminatorStartsWith("type")("A", (_) => 1 as const),
312
+ * Match.discriminatorStartsWith("type")("B", (_) => 2 as const),
313
+ * Match.orElse((_) => 3 as const)
314
+ * )
315
+ *
316
+ * console.log(match({ type: "A" })) // 1
317
+ * console.log(match({ type: "B" })) // 2
318
+ * console.log(match({ type: "A.A" })) // 1
319
+ * ```
320
+ *
321
+ * @category Defining patterns
55
322
  * @since 1.0.0
56
323
  */
57
324
  export const discriminatorStartsWith = internal.discriminatorStartsWith;
58
325
  /**
59
- * @category combinators
326
+ * Matches values based on a field that serves as a discriminator, mapping each
327
+ * possible value to a corresponding handler.
328
+ *
329
+ * **Details**
330
+ *
331
+ * This function simplifies working with discriminated unions by letting you
332
+ * define a set of handlers for each possible value of a given field. Instead of
333
+ * chaining multiple calls to {@link discriminator}, this function allows
334
+ * defining all possible cases at once using an object where the keys are the
335
+ * possible values of the field, and the values are the corresponding handler
336
+ * functions.
337
+ *
338
+ * @example
339
+ * ```ts
340
+ * import { Match, pipe } from "effect"
341
+ *
342
+ * const match = pipe(
343
+ * Match.type<{ type: "A"; a: string } | { type: "B"; b: number } | { type: "C"; c: boolean }>(),
344
+ * Match.discriminators("type")({
345
+ * A: (a) => a.a,
346
+ * B: (b) => b.b,
347
+ * C: (c) => c.c
348
+ * }),
349
+ * Match.exhaustive
350
+ * )
351
+ * ```
352
+ *
353
+ * @category Defining patterns
60
354
  * @since 1.0.0
61
355
  */
62
356
  export const discriminators = internal.discriminators;
63
357
  /**
64
- * @category combinators
358
+ * Matches values based on a discriminator field and **ensures all cases are
359
+ * handled**.
360
+ *
361
+ * **Details*+
362
+ *
363
+ * This function is similar to {@link discriminators}, but **requires that all
364
+ * possible cases** are explicitly handled. It is useful when working with
365
+ * discriminated unions, where a specific field (e.g., `"type"`) determines the
366
+ * shape of an object. Each possible value of the field must have a
367
+ * corresponding handler, ensuring **exhaustiveness checking** at compile time.
368
+ *
369
+ * This function **does not require** `Match.exhaustive` at the end of the
370
+ * pipeline because it enforces exhaustiveness by design.
371
+ *
372
+ * @example
373
+ * ```ts
374
+ * import { Match, pipe } from "effect"
375
+ *
376
+ * const match = pipe(
377
+ * Match.type<{ type: "A"; a: string } | { type: "B"; b: number } | { type: "C"; c: boolean }>(),
378
+ * Match.discriminatorsExhaustive("type")({
379
+ * A: (a) => a.a,
380
+ * B: (b) => b.b,
381
+ * C: (c) => c.c
382
+ * })
383
+ * )
384
+ * ```
385
+ *
386
+ * @category Defining patterns
65
387
  * @since 1.0.0
66
388
  */
67
389
  export const discriminatorsExhaustive = internal.discriminatorsExhaustive;
68
390
  /**
69
- * @category combinators
391
+ * The `Match.tag` function allows pattern matching based on the `_tag` field in
392
+ * a [Discriminated Union](https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes-func.html#discriminated-unions).
393
+ * You can specify multiple tags to match within a single pattern.
394
+ *
395
+ * **Note**
396
+ *
397
+ * The `Match.tag` function relies on the convention within the Effect ecosystem
398
+ * of naming the tag field as `"_tag"`. Ensure that your discriminated unions
399
+ * follow this naming convention for proper functionality.
400
+ *
401
+ * @example
402
+ * ```ts
403
+ * // Title: Matching a Discriminated Union by Tag
404
+ * import { Match } from "effect"
405
+ *
406
+ * type Event =
407
+ * | { readonly _tag: "fetch" }
408
+ * | { readonly _tag: "success"; readonly data: string }
409
+ * | { readonly _tag: "error"; readonly error: Error }
410
+ * | { readonly _tag: "cancel" }
411
+ *
412
+ * // Create a Matcher for Either<number, string>
413
+ * const match = Match.type<Event>().pipe(
414
+ * // Match either "fetch" or "success"
415
+ * Match.tag("fetch", "success", () => `Ok!`),
416
+ * // Match "error" and extract the error message
417
+ * Match.tag("error", (event) => `Error: ${event.error.message}`),
418
+ * // Match "cancel"
419
+ * Match.tag("cancel", () => "Cancelled"),
420
+ * Match.exhaustive
421
+ * )
422
+ *
423
+ * console.log(match({ _tag: "success", data: "Hello" }))
424
+ * // Output: "Ok!"
425
+ *
426
+ * console.log(match({ _tag: "error", error: new Error("Oops!") }))
427
+ * // Output: "Error: Oops!"
428
+ * ```
429
+ *
430
+ * @category Defining patterns
70
431
  * @since 1.0.0
71
432
  */
72
433
  export const tag = internal.tag;
73
434
  /**
74
- * @category combinators
435
+ * Matches values where the `_tag` field starts with a given prefix.
436
+ *
437
+ * **Details**
438
+ *
439
+ * This function allows you to match on values in a **discriminated union**
440
+ * based on whether the `_tag` field starts with a specified prefix. It is
441
+ * useful for handling hierarchical or namespaced tags, where multiple related
442
+ * cases share a common prefix.
443
+ *
444
+ * @example
445
+ * ```ts
446
+ * import { Match, pipe } from "effect"
447
+ *
448
+ * const match = pipe(
449
+ * Match.type<{ _tag: "A" } | { _tag: "B" } | { _tag: "A.A" } | {}>(),
450
+ * Match.tagStartsWith("A", (_) => 1 as const),
451
+ * Match.tagStartsWith("B", (_) => 2 as const),
452
+ * Match.orElse((_) => 3 as const)
453
+ * )
454
+ *
455
+ * console.log(match({ _tag: "A" })) // 1
456
+ * console.log(match({ _tag: "B" })) // 2
457
+ * console.log(match({ _tag: "A.A" })) // 1
458
+ * ```
459
+ *
460
+ * @category Defining patterns
75
461
  * @since 1.0.0
76
462
  */
77
463
  export const tagStartsWith = internal.tagStartsWith;
78
464
  /**
79
- * @category combinators
465
+ * Matches values based on their `_tag` field, mapping each tag to a
466
+ * corresponding handler.
467
+ *
468
+ * **Details**
469
+ *
470
+ * This function provides a way to handle discriminated unions by mapping `_tag`
471
+ * values to specific functions. Each handler receives the matched value and
472
+ * returns a transformed result. If all possible tags are handled, you can
473
+ * enforce exhaustiveness using `Match.exhaustive` to ensure no case is missed.
474
+ *
475
+ * @example
476
+ * ```ts
477
+ * import { Match, pipe } from "effect"
478
+ *
479
+ * const match = pipe(
480
+ * Match.type<{ _tag: "A"; a: string } | { _tag: "B"; b: number } | { _tag: "C"; c: boolean }>(),
481
+ * Match.tags({
482
+ * A: (a) => a.a,
483
+ * B: (b) => b.b,
484
+ * C: (c) => c.c
485
+ * }),
486
+ * Match.exhaustive
487
+ * )
488
+ * ```
489
+ *
490
+ * @category Defining patterns
80
491
  * @since 1.0.0
81
492
  */
82
493
  export const tags = internal.tags;
83
494
  /**
84
- * @category combinators
495
+ * Matches values based on their `_tag` field and requires handling of all
496
+ * possible cases.
497
+ *
498
+ * **Details**
499
+ *
500
+ * This function is designed for **discriminated unions** where every possible
501
+ * `_tag` value must have a corresponding handler. Unlike {@link tags}, this
502
+ * function ensures **exhaustiveness**, meaning all cases must be explicitly
503
+ * handled. If a `_tag` value is missing from the mapping, TypeScript will
504
+ * report an error.
505
+ *
506
+ * @example
507
+ * ```ts
508
+ * import { Match, pipe } from "effect"
509
+ *
510
+ * const match = pipe(
511
+ * Match.type<{ _tag: "A"; a: string } | { _tag: "B"; b: number } | { _tag: "C"; c: boolean }>(),
512
+ * Match.tagsExhaustive({
513
+ * A: (a) => a.a,
514
+ * B: (b) => b.b,
515
+ * C: (c) => c.c
516
+ * })
517
+ * )
518
+ * ```
519
+ *
520
+ * @category Defining patterns
85
521
  * @since 1.0.0
86
522
  */
87
523
  export const tagsExhaustive = internal.tagsExhaustive;
88
524
  /**
89
- * @category combinators
525
+ * Excludes a specific value from matching while allowing all others.
526
+ *
527
+ * **Details**
528
+ *
529
+ * This function is useful when you need to **handle all values except one or
530
+ * more specific cases**. Instead of listing all possible matches manually, this
531
+ * function simplifies the logic by allowing you to specify values to exclude.
532
+ * Any excluded value will bypass the provided function and continue matching
533
+ * through other cases.
534
+ *
535
+ * @example
536
+ * ```ts
537
+ * // Title: Ignoring a Specific Value
538
+ * import { Match } from "effect"
539
+ *
540
+ * // Create a matcher for string or number values
541
+ * const match = Match.type<string | number>().pipe(
542
+ * // Match any value except "hi", returning "ok"
543
+ * Match.not("hi", () => "ok"),
544
+ * // Fallback case for when the value is "hi"
545
+ * Match.orElse(() => "fallback")
546
+ * )
547
+ *
548
+ * console.log(match("hello"))
549
+ * // Output: "ok"
550
+ *
551
+ * console.log(match("hi"))
552
+ * // Output: "fallback"
553
+ * ```
554
+ *
555
+ * @category Defining patterns
90
556
  * @since 1.0.0
91
557
  */
92
558
  export const not = internal.not;
93
559
  /**
94
- * @category predicates
560
+ * Matches non-empty strings.
561
+ *
562
+ * @category Predicates
95
563
  * @since 1.0.0
96
564
  */
97
565
  export const nonEmptyString = internal.nonEmptyString;
98
566
  /**
99
- * @category predicates
567
+ * Matches a specific set of literal values (e.g., `Match.is("a", 42, true)`).
568
+ *
569
+ * @category Predicates
100
570
  * @since 1.0.0
101
571
  */
102
572
  export const is = internal.is;
103
573
  /**
104
- * @category predicates
574
+ * Matches values of type `string`.
575
+ *
576
+ * @category Predicates
105
577
  * @since 1.0.0
106
578
  */
107
579
  export const string = Predicate.isString;
108
580
  /**
109
- * @category predicates
581
+ * Matches values of type `number`.
582
+ *
583
+ * @category Predicates
110
584
  * @since 1.0.0
111
585
  */
112
586
  export const number = Predicate.isNumber;
113
587
  /**
114
- * @category predicates
588
+ * Matches any value without restrictions.
589
+ *
590
+ * @category Predicates
115
591
  * @since 1.0.0
116
592
  */
117
593
  export const any = internal.any;
118
594
  /**
119
- * @category predicates
595
+ * Matches any defined (non-null and non-undefined) value.
596
+ *
597
+ * @category Predicates
120
598
  * @since 1.0.0
121
599
  */
122
600
  export const defined = internal.defined;
123
601
  /**
124
- * @category predicates
602
+ * Matches values of type `boolean`.
603
+ *
604
+ * @category Predicates
125
605
  * @since 1.0.0
126
606
  */
127
607
  export const boolean = Predicate.isBoolean;
128
608
  const _undefined = Predicate.isUndefined;
129
609
  export {
130
610
  /**
131
- * @category predicates
611
+ * Matches the value `undefined`.
612
+ *
613
+ * @category Predicates
132
614
  * @since 1.0.0
133
615
  */
134
616
  _undefined as undefined };
135
617
  const _null = Predicate.isNull;
136
618
  export {
137
619
  /**
138
- * @category predicates
620
+ * Matches the value `null`.
621
+ *
622
+ * @category Predicates
139
623
  * @since 1.0.0
140
624
  */
141
625
  _null as null };
142
626
  /**
143
- * @category predicates
627
+ * Matches values of type `bigint`.
628
+ *
629
+ * @category Predicates
144
630
  * @since 1.0.0
145
631
  */
146
632
  export const bigint = Predicate.isBigInt;
147
633
  /**
148
- * @category predicates
634
+ * Matches values of type `symbol`.
635
+ *
636
+ * @category Predicates
149
637
  * @since 1.0.0
150
638
  */
151
639
  export const symbol = Predicate.isSymbol;
152
640
  /**
153
- * @category predicates
641
+ * Matches values that are instances of `Date`.
642
+ *
643
+ * @category Predicates
154
644
  * @since 1.0.0
155
645
  */
156
646
  export const date = Predicate.isDate;
157
647
  /**
158
- * @category predicates
648
+ * Matches objects where keys are `string` or `symbol` and values are `unknown`.
649
+ *
650
+ * @category Predicates
159
651
  * @since 1.0.0
160
652
  */
161
653
  export const record = Predicate.isRecord;
162
654
  /**
163
- * @category predicates
655
+ * Matches instances of a given class.
656
+ *
657
+ * @category Predicates
164
658
  * @since 1.0.0
165
659
  */
166
660
  export const instanceOf = internal.instanceOf;
167
661
  /**
168
- * @category predicates
662
+ * @category Predicates
169
663
  * @since 1.0.0
170
664
  */
171
665
  export const instanceOfUnsafe = internal.instanceOf;
172
666
  /**
173
- * @category conversions
667
+ * Provides a fallback value when no patterns match.
668
+ *
669
+ * **Details**
670
+ *
671
+ * This function ensures that a matcher always returns a valid result, even if
672
+ * no defined patterns match. It acts as a default case, similar to the
673
+ * `default` clause in a `switch` statement or the final `else` in an `if-else`
674
+ * chain.
675
+ *
676
+ * @example
677
+ * ```ts
678
+ * // Title: Providing a Default Value When No Patterns Match
679
+ * import { Match } from "effect"
680
+ *
681
+ * // Create a matcher for string or number values
682
+ * const match = Match.type<string | number>().pipe(
683
+ * // Match when the value is "a"
684
+ * Match.when("a", () => "ok"),
685
+ * // Fallback when no patterns match
686
+ * Match.orElse(() => "fallback")
687
+ * )
688
+ *
689
+ * console.log(match("a"))
690
+ * // Output: "ok"
691
+ *
692
+ * console.log(match("b"))
693
+ * // Output: "fallback"
694
+ * ```
695
+ *
696
+ * @category Completion
174
697
  * @since 1.0.0
175
698
  */
176
699
  export const orElse = internal.orElse;
177
- /**
178
- * @category conversions
700
+ // TODO(4.0): Rename to "orThrow"? Like Either.getOrThrow
701
+ /**
702
+ * Throws an error if no pattern matches.
703
+ *
704
+ * **Details**
705
+ *
706
+ * This function finalizes a matcher by ensuring that if no patterns match, an
707
+ * error is thrown. It is useful when all cases should be covered, and any
708
+ * unexpected input should trigger an error instead of returning a default
709
+ * value.
710
+ *
711
+ * When used, this function removes the need for an explicit fallback case and
712
+ * ensures that an unmatched value is never silently ignored.
713
+ *
714
+ * @category Completion
179
715
  * @since 1.0.0
180
716
  */
181
717
  export const orElseAbsurd = internal.orElseAbsurd;
182
718
  /**
183
- * @category conversions
719
+ * Wraps the match result in an `Either`, distinguishing matched and unmatched
720
+ * cases.
721
+ *
722
+ * **Details**
723
+ *
724
+ * This function ensures that the result of a matcher is always wrapped in an
725
+ * `Either`, allowing clear differentiation between successful matches
726
+ * (`Right(value)`) and cases where no pattern matched (`Left(unmatched
727
+ * value)`).
728
+ *
729
+ * This approach is particularly useful when handling optional values or when an
730
+ * unmatched case should be explicitly handled rather than returning a default
731
+ * value or throwing an error.
732
+ *
733
+ * @example
734
+ * ```ts
735
+ * // Title: Extracting a User Role with Either
736
+ * import { Match } from "effect"
737
+ *
738
+ * type User = { readonly role: "admin" | "editor" | "viewer" }
739
+ *
740
+ * // Create a matcher to extract user roles
741
+ * const getRole = Match.type<User>().pipe(
742
+ * Match.when({ role: "admin" }, () => "Has full access"),
743
+ * Match.when({ role: "editor" }, () => "Can edit content"),
744
+ * Match.either // Wrap the result in an Either
745
+ * )
746
+ *
747
+ * console.log(getRole({ role: "admin" }))
748
+ * // Output: { _id: 'Either', _tag: 'Right', right: 'Has full access' }
749
+ *
750
+ * console.log(getRole({ role: "viewer" }))
751
+ * // Output: { _id: 'Either', _tag: 'Left', left: { role: 'viewer' } }
752
+ * ```
753
+ *
754
+ * @category Completion
184
755
  * @since 1.0.0
185
756
  */
186
757
  export const either = internal.either;
187
758
  /**
188
- * @category conversions
759
+ * Wraps the match result in an `Option`, representing an optional match.
760
+ *
761
+ * **Details**
762
+ *
763
+ * This function ensures that the result of a matcher is wrapped in an `Option`,
764
+ * making it easy to handle cases where no pattern matches. If a match is found,
765
+ * it returns `Some(value)`, otherwise, it returns `None`.
766
+ *
767
+ * This is useful in cases where a missing match is expected and should be
768
+ * handled explicitly rather than throwing an error or returning a default
769
+ * value.
770
+ *
771
+ * @example
772
+ * ```ts
773
+ * // Title: Extracting a User Role with Option
774
+ * import { Match } from "effect"
775
+ *
776
+ * type User = { readonly role: "admin" | "editor" | "viewer" }
777
+ *
778
+ * // Create a matcher to extract user roles
779
+ * const getRole = Match.type<User>().pipe(
780
+ * Match.when({ role: "admin" }, () => "Has full access"),
781
+ * Match.when({ role: "editor" }, () => "Can edit content"),
782
+ * Match.option // Wrap the result in an Option
783
+ * )
784
+ *
785
+ * console.log(getRole({ role: "admin" }))
786
+ * // Output: { _id: 'Option', _tag: 'Some', value: 'Has full access' }
787
+ *
788
+ * console.log(getRole({ role: "viewer" }))
789
+ * // Output: { _id: 'Option', _tag: 'None' }
790
+ * ```
791
+ *
792
+ * @category Completion
189
793
  * @since 1.0.0
190
794
  */
191
795
  export const option = internal.option;
192
796
  /**
193
- * @category conversions
797
+ * The `Match.exhaustive` method finalizes the pattern matching process by
798
+ * ensuring that all possible cases are accounted for. If any case is missing,
799
+ * TypeScript will produce a type error. This is particularly useful when
800
+ * working with unions, as it helps prevent unintended gaps in pattern matching.
801
+ *
802
+ * @example
803
+ * ```ts
804
+ * // Title: Ensuring All Cases Are Covered
805
+ * import { Match } from "effect"
806
+ *
807
+ * // Create a matcher for string or number values
808
+ * const match = Match.type<string | number>().pipe(
809
+ * // Match when the value is a number
810
+ * Match.when(Match.number, (n) => `number: ${n}`),
811
+ * // Mark the match as exhaustive, ensuring all cases are handled
812
+ * // TypeScript will throw an error if any case is missing
813
+ * // @ts-expect-error Type 'string' is not assignable to type 'never'
814
+ * Match.exhaustive
815
+ * )
816
+ * ```
817
+ *
818
+ * @category Completion
194
819
  * @since 1.0.0
195
820
  */
196
821
  export const exhaustive = internal.exhaustive;
197
822
  /**
198
823
  * @since 1.0.0
199
- * @category type ids
824
+ * @category Symbols
200
825
  */
201
826
  export const SafeRefinementId = /*#__PURE__*/Symbol.for("effect/SafeRefinement");
202
827
  const Fail = /*#__PURE__*/Symbol.for("effect/Fail");