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