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.
- package/README.md +38 -49
- package/dist/cjs/Channel.js.map +1 -1
- package/dist/cjs/DateTime.js +17 -1
- package/dist/cjs/DateTime.js.map +1 -1
- package/dist/cjs/Differ.js.map +1 -1
- package/dist/cjs/Duration.js +128 -1
- package/dist/cjs/Duration.js.map +1 -1
- package/dist/cjs/Effect.js +175 -37
- package/dist/cjs/Effect.js.map +1 -1
- package/dist/cjs/Either.js +2 -1
- package/dist/cjs/Either.js.map +1 -1
- package/dist/cjs/FiberHandle.js +54 -21
- package/dist/cjs/FiberHandle.js.map +1 -1
- package/dist/cjs/FiberMap.js +51 -24
- package/dist/cjs/FiberMap.js.map +1 -1
- package/dist/cjs/FiberSet.js +50 -17
- package/dist/cjs/FiberSet.js.map +1 -1
- package/dist/cjs/HashMap.js +19 -1
- package/dist/cjs/HashMap.js.map +1 -1
- package/dist/cjs/HashSet.js +9 -1
- package/dist/cjs/HashSet.js.map +1 -1
- package/dist/cjs/Layer.js +21 -1
- package/dist/cjs/Layer.js.map +1 -1
- package/dist/cjs/Match.js +659 -38
- package/dist/cjs/Match.js.map +1 -1
- package/dist/cjs/RcMap.js +11 -1
- package/dist/cjs/RcMap.js.map +1 -1
- package/dist/cjs/Reloadable.js.map +1 -1
- package/dist/cjs/STM.js.map +1 -1
- package/dist/cjs/Schedule.js +1074 -309
- package/dist/cjs/Schedule.js.map +1 -1
- package/dist/cjs/Schema.js +73 -1
- package/dist/cjs/Schema.js.map +1 -1
- package/dist/cjs/Stream.js.map +1 -1
- package/dist/cjs/internal/channel.js.map +1 -1
- package/dist/cjs/internal/core-effect.js.map +1 -1
- package/dist/cjs/internal/core.js +27 -3
- package/dist/cjs/internal/core.js.map +1 -1
- package/dist/cjs/internal/dateTime.js +4 -1
- package/dist/cjs/internal/dateTime.js.map +1 -1
- package/dist/cjs/internal/differ.js +4 -0
- package/dist/cjs/internal/differ.js.map +1 -1
- package/dist/cjs/internal/effect/circular.js +3 -2
- package/dist/cjs/internal/effect/circular.js.map +1 -1
- package/dist/cjs/internal/fiberRuntime.js +21 -7
- package/dist/cjs/internal/fiberRuntime.js.map +1 -1
- package/dist/cjs/internal/hashMap.js +10 -1
- package/dist/cjs/internal/hashMap.js.map +1 -1
- package/dist/cjs/internal/keyedPool.js +1 -1
- package/dist/cjs/internal/keyedPool.js.map +1 -1
- package/dist/cjs/internal/layer.js.map +1 -1
- package/dist/cjs/internal/rcMap.js +86 -56
- package/dist/cjs/internal/rcMap.js.map +1 -1
- package/dist/cjs/internal/reloadable.js.map +1 -1
- package/dist/cjs/internal/schedule.js.map +1 -1
- package/dist/cjs/internal/sink.js.map +1 -1
- package/dist/cjs/internal/stm/stm.js.map +1 -1
- package/dist/cjs/internal/stream.js.map +1 -1
- package/dist/cjs/internal/version.js +1 -1
- package/dist/cjs/internal/version.js.map +1 -1
- package/dist/dts/Channel.d.ts +4 -4
- package/dist/dts/Channel.d.ts.map +1 -1
- package/dist/dts/DateTime.d.ts +16 -0
- package/dist/dts/DateTime.d.ts.map +1 -1
- package/dist/dts/Differ.d.ts +2 -1
- package/dist/dts/Differ.d.ts.map +1 -1
- package/dist/dts/Duration.d.ts +64 -0
- package/dist/dts/Duration.d.ts.map +1 -1
- package/dist/dts/Effect.d.ts +402 -30
- package/dist/dts/Effect.d.ts.map +1 -1
- package/dist/dts/Either.d.ts +7 -0
- package/dist/dts/Either.d.ts.map +1 -1
- package/dist/dts/FiberHandle.d.ts +26 -0
- package/dist/dts/FiberHandle.d.ts.map +1 -1
- package/dist/dts/FiberMap.d.ts +26 -0
- package/dist/dts/FiberMap.d.ts.map +1 -1
- package/dist/dts/FiberSet.d.ts +25 -0
- package/dist/dts/FiberSet.d.ts.map +1 -1
- package/dist/dts/HashMap.d.ts +38 -0
- package/dist/dts/HashMap.d.ts.map +1 -1
- package/dist/dts/HashSet.d.ts +7 -0
- package/dist/dts/HashSet.d.ts.map +1 -1
- package/dist/dts/Layer.d.ts +32 -13
- package/dist/dts/Layer.d.ts.map +1 -1
- package/dist/dts/Match.d.ts +731 -48
- package/dist/dts/Match.d.ts.map +1 -1
- package/dist/dts/RcMap.d.ts +32 -0
- package/dist/dts/RcMap.d.ts.map +1 -1
- package/dist/dts/Reloadable.d.ts +13 -13
- package/dist/dts/Reloadable.d.ts.map +1 -1
- package/dist/dts/STM.d.ts +4 -4
- package/dist/dts/STM.d.ts.map +1 -1
- package/dist/dts/Schedule.d.ts +2294 -633
- package/dist/dts/Schedule.d.ts.map +1 -1
- package/dist/dts/Schema.d.ts +40 -4
- package/dist/dts/Schema.d.ts.map +1 -1
- package/dist/dts/Stream.d.ts +8 -8
- package/dist/dts/Stream.d.ts.map +1 -1
- package/dist/dts/Trie.d.ts +7 -7
- package/dist/dts/Trie.d.ts.map +1 -1
- package/dist/dts/index.d.ts +25 -0
- package/dist/dts/index.d.ts.map +1 -1
- package/dist/dts/internal/stm/stm.d.ts +2 -2
- package/dist/dts/internal/stm/stm.d.ts.map +1 -1
- package/dist/esm/Channel.js.map +1 -1
- package/dist/esm/DateTime.js +16 -0
- package/dist/esm/DateTime.js.map +1 -1
- package/dist/esm/Differ.js.map +1 -1
- package/dist/esm/Duration.js +124 -0
- package/dist/esm/Duration.js.map +1 -1
- package/dist/esm/Effect.js +170 -32
- package/dist/esm/Effect.js.map +1 -1
- package/dist/esm/Either.js +7 -0
- package/dist/esm/Either.js.map +1 -1
- package/dist/esm/FiberHandle.js +48 -18
- package/dist/esm/FiberHandle.js.map +1 -1
- package/dist/esm/FiberMap.js +46 -22
- package/dist/esm/FiberMap.js.map +1 -1
- package/dist/esm/FiberSet.js +45 -15
- package/dist/esm/FiberSet.js.map +1 -1
- package/dist/esm/HashMap.js +17 -0
- package/dist/esm/HashMap.js.map +1 -1
- package/dist/esm/HashSet.js +7 -0
- package/dist/esm/HashSet.js.map +1 -1
- package/dist/esm/Layer.js +20 -0
- package/dist/esm/Layer.js.map +1 -1
- package/dist/esm/Match.js +665 -40
- package/dist/esm/Match.js.map +1 -1
- package/dist/esm/RcMap.js +10 -0
- package/dist/esm/RcMap.js.map +1 -1
- package/dist/esm/Reloadable.js.map +1 -1
- package/dist/esm/STM.js.map +1 -1
- package/dist/esm/Schedule.js +1074 -309
- package/dist/esm/Schedule.js.map +1 -1
- package/dist/esm/Schema.js +71 -0
- package/dist/esm/Schema.js.map +1 -1
- package/dist/esm/Stream.js.map +1 -1
- package/dist/esm/index.js +25 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/internal/channel.js.map +1 -1
- package/dist/esm/internal/core-effect.js.map +1 -1
- package/dist/esm/internal/core.js +23 -0
- package/dist/esm/internal/core.js.map +1 -1
- package/dist/esm/internal/dateTime.js +2 -0
- package/dist/esm/internal/dateTime.js.map +1 -1
- package/dist/esm/internal/differ.js +4 -0
- package/dist/esm/internal/differ.js.map +1 -1
- package/dist/esm/internal/effect/circular.js +3 -2
- package/dist/esm/internal/effect/circular.js.map +1 -1
- package/dist/esm/internal/fiberRuntime.js +18 -5
- package/dist/esm/internal/fiberRuntime.js.map +1 -1
- package/dist/esm/internal/hashMap.js +9 -0
- package/dist/esm/internal/hashMap.js.map +1 -1
- package/dist/esm/internal/keyedPool.js +1 -1
- package/dist/esm/internal/keyedPool.js.map +1 -1
- package/dist/esm/internal/layer.js.map +1 -1
- package/dist/esm/internal/rcMap.js +85 -55
- package/dist/esm/internal/rcMap.js.map +1 -1
- package/dist/esm/internal/reloadable.js.map +1 -1
- package/dist/esm/internal/schedule.js.map +1 -1
- package/dist/esm/internal/sink.js.map +1 -1
- package/dist/esm/internal/stm/stm.js.map +1 -1
- package/dist/esm/internal/stream.js.map +1 -1
- package/dist/esm/internal/version.js +1 -1
- package/dist/esm/internal/version.js.map +1 -1
- package/package.json +2 -1
- package/src/Channel.ts +14 -17
- package/src/DateTime.ts +17 -8
- package/src/Differ.ts +2 -1
- package/src/Duration.ts +147 -0
- package/src/Effect.ts +528 -140
- package/src/Either.ts +9 -0
- package/src/FiberHandle.ts +95 -35
- package/src/FiberMap.ts +104 -39
- package/src/FiberSet.ts +93 -24
- package/src/HashMap.ts +40 -0
- package/src/HashSet.ts +8 -0
- package/src/Layer.ts +94 -40
- package/src/Match.ts +733 -49
- package/src/RcMap.ts +34 -0
- package/src/Reloadable.ts +17 -27
- package/src/STM.ts +10 -17
- package/src/Schedule.ts +2325 -653
- package/src/Schema.ts +81 -4
- package/src/Stream.ts +26 -33
- package/src/Trie.ts +7 -7
- package/src/index.ts +25 -0
- package/src/internal/channel.ts +37 -39
- package/src/internal/core-effect.ts +84 -84
- package/src/internal/core.ts +80 -0
- package/src/internal/dateTime.ts +3 -0
- package/src/internal/differ.ts +4 -0
- package/src/internal/effect/circular.ts +3 -2
- package/src/internal/fiberRuntime.ts +31 -6
- package/src/internal/hashMap.ts +16 -0
- package/src/internal/keyedPool.ts +1 -1
- package/src/internal/layer.ts +52 -52
- package/src/internal/rcMap.ts +131 -89
- package/src/internal/reloadable.ts +25 -28
- package/src/internal/schedule.ts +29 -23
- package/src/internal/sink.ts +16 -15
- package/src/internal/stm/stm.ts +54 -46
- package/src/internal/stream.ts +100 -100
- 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
|
|
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
|
|
44
|
+
* @category Symbols
|
|
20
45
|
* @since 1.0.0
|
|
21
46
|
*/
|
|
22
47
|
export type MatcherTypeId = typeof MatcherTypeId
|
|
23
48
|
|
|
24
49
|
/**
|
|
25
|
-
*
|
|
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
|
|
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
|
|
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
|
|
128
|
+
* @category Model
|
|
70
129
|
* @since 1.0.0
|
|
71
130
|
*/
|
|
72
131
|
export type Case = When | Not
|
|
73
132
|
|
|
74
133
|
/**
|
|
75
|
-
* @category
|
|
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
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
|
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
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
|
773
|
+
> = internal.tagStartsWith
|
|
329
774
|
|
|
330
775
|
/**
|
|
331
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
|
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
|
|
1229
|
+
* @category Symbols
|
|
546
1230
|
*/
|
|
547
1231
|
export type SafeRefinementId = typeof SafeRefinementId
|
|
548
1232
|
|
|
549
1233
|
/**
|
|
550
|
-
* @category
|
|
1234
|
+
* @category Model
|
|
551
1235
|
* @since 1.0.0
|
|
552
1236
|
*/
|
|
553
1237
|
export interface SafeRefinement<in A, out R = A> {
|