effect 3.16.13 → 3.16.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/Predicate.js +516 -200
- package/dist/cjs/Predicate.js.map +1 -1
- package/dist/cjs/Schema.js +2 -2
- package/dist/cjs/Schema.js.map +1 -1
- package/dist/cjs/internal/channel.js +2 -2
- package/dist/cjs/internal/channel.js.map +1 -1
- package/dist/cjs/internal/core-effect.js +1 -0
- package/dist/cjs/internal/core-effect.js.map +1 -1
- package/dist/cjs/internal/dataSource.js +2 -2
- package/dist/cjs/internal/dataSource.js.map +1 -1
- package/dist/cjs/internal/fiberRuntime.js +1 -1
- package/dist/cjs/internal/fiberRuntime.js.map +1 -1
- package/dist/cjs/internal/groupBy.js +2 -2
- package/dist/cjs/internal/groupBy.js.map +1 -1
- package/dist/cjs/internal/sink.js +4 -4
- package/dist/cjs/internal/sink.js.map +1 -1
- package/dist/cjs/internal/stm/stm.js +3 -3
- package/dist/cjs/internal/stm/stm.js.map +1 -1
- package/dist/cjs/internal/stream.js +5 -5
- package/dist/cjs/internal/stream.js.map +1 -1
- package/dist/cjs/internal/version.js +1 -1
- package/dist/dts/Effect.d.ts +1 -1
- package/dist/dts/Effect.d.ts.map +1 -1
- package/dist/dts/Predicate.d.ts +1190 -375
- package/dist/dts/Predicate.d.ts.map +1 -1
- package/dist/dts/index.d.ts +15 -0
- package/dist/dts/index.d.ts.map +1 -1
- package/dist/dts/internal/core-effect.d.ts.map +1 -1
- package/dist/dts/internal/stm/stm.d.ts.map +1 -1
- package/dist/dts/internal/stream.d.ts.map +1 -1
- package/dist/esm/Predicate.js +516 -200
- package/dist/esm/Predicate.js.map +1 -1
- package/dist/esm/Schema.js +2 -2
- package/dist/esm/Schema.js.map +1 -1
- package/dist/esm/index.js +15 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/internal/channel.js +2 -2
- package/dist/esm/internal/channel.js.map +1 -1
- package/dist/esm/internal/core-effect.js +1 -0
- package/dist/esm/internal/core-effect.js.map +1 -1
- package/dist/esm/internal/dataSource.js +2 -2
- package/dist/esm/internal/dataSource.js.map +1 -1
- package/dist/esm/internal/fiberRuntime.js +1 -1
- package/dist/esm/internal/fiberRuntime.js.map +1 -1
- package/dist/esm/internal/groupBy.js +2 -2
- package/dist/esm/internal/groupBy.js.map +1 -1
- package/dist/esm/internal/sink.js +4 -4
- package/dist/esm/internal/sink.js.map +1 -1
- package/dist/esm/internal/stm/stm.js +3 -3
- package/dist/esm/internal/stm/stm.js.map +1 -1
- package/dist/esm/internal/stream.js +5 -5
- package/dist/esm/internal/stream.js.map +1 -1
- package/dist/esm/internal/version.js +1 -1
- package/package.json +1 -1
- package/src/Effect.ts +1 -1
- package/src/Predicate.ts +1213 -377
- package/src/Schema.ts +2 -2
- package/src/index.ts +15 -0
- package/src/internal/channel.ts +2 -2
- package/src/internal/core-effect.ts +1 -0
- package/src/internal/dataSource.ts +12 -14
- package/src/internal/fiberRuntime.ts +2 -2
- package/src/internal/groupBy.ts +12 -14
- package/src/internal/sink.ts +13 -15
- package/src/internal/stm/stm.ts +16 -20
- package/src/internal/stream.ts +17 -23
- package/src/internal/version.ts +1 -1
package/src/Predicate.ts
CHANGED
|
@@ -1,4 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
|
+
* This module provides a collection of functions for working with predicates and refinements.
|
|
3
|
+
*
|
|
4
|
+
* A `Predicate<A>` is a function that takes a value of type `A` and returns a boolean.
|
|
5
|
+
* It is used to check if a value satisfies a certain condition.
|
|
6
|
+
*
|
|
7
|
+
* A `Refinement<A, B>` is a special type of predicate that not only checks a condition
|
|
8
|
+
* but also provides a type guard, allowing TypeScript to narrow the type of the input
|
|
9
|
+
* value from `A` to a more specific type `B` within a conditional block.
|
|
10
|
+
*
|
|
11
|
+
* The module includes:
|
|
12
|
+
* - Basic predicates and refinements for common types (e.g., `isString`, `isNumber`).
|
|
13
|
+
* - Combinators to create new predicates from existing ones (e.g., `and`, `or`, `not`).
|
|
14
|
+
* - Advanced combinators for working with data structures (e.g., `tuple`, `struct`).
|
|
15
|
+
* - Type-level utilities for inspecting predicate and refinement types.
|
|
16
|
+
*
|
|
2
17
|
* @since 2.0.0
|
|
3
18
|
*/
|
|
4
19
|
import { dual, isFunction as isFunction_ } from "./Function.js"
|
|
@@ -6,6 +21,20 @@ import type { TypeLambda } from "./HKT.js"
|
|
|
6
21
|
import type { TupleOf, TupleOfAtLeast } from "./Types.js"
|
|
7
22
|
|
|
8
23
|
/**
|
|
24
|
+
* Represents a function that takes a value of type `A` and returns `true` if the value
|
|
25
|
+
* satisfies some condition, `false` otherwise.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```ts
|
|
29
|
+
* import { Predicate } from "effect"
|
|
30
|
+
* import * as assert from "node:assert"
|
|
31
|
+
*
|
|
32
|
+
* const isEven: Predicate.Predicate<number> = (n) => n % 2 === 0
|
|
33
|
+
*
|
|
34
|
+
* assert.strictEqual(isEven(2), true)
|
|
35
|
+
* assert.strictEqual(isEven(3), false)
|
|
36
|
+
* ```
|
|
37
|
+
*
|
|
9
38
|
* @category models
|
|
10
39
|
* @since 2.0.0
|
|
11
40
|
*/
|
|
@@ -14,6 +43,9 @@ export interface Predicate<in A> {
|
|
|
14
43
|
}
|
|
15
44
|
|
|
16
45
|
/**
|
|
46
|
+
* A `TypeLambda` for `Predicate`. This is used to support higher-kinded types
|
|
47
|
+
* and allows `Predicate` to be used in generic contexts within the `effect` ecosystem.
|
|
48
|
+
*
|
|
17
49
|
* @category type lambdas
|
|
18
50
|
* @since 2.0.0
|
|
19
51
|
*/
|
|
@@ -22,6 +54,27 @@ export interface PredicateTypeLambda extends TypeLambda {
|
|
|
22
54
|
}
|
|
23
55
|
|
|
24
56
|
/**
|
|
57
|
+
* Represents a function that serves as a type guard.
|
|
58
|
+
*
|
|
59
|
+
* A `Refinement<A, B>` is a function that takes a value of type `A` and returns a
|
|
60
|
+
* type predicate `a is B`, where `B` is a subtype of `A`. If the function returns
|
|
61
|
+
* `true`, TypeScript will narrow the type of the input variable to `B`.
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```ts
|
|
65
|
+
* import { Predicate } from "effect"
|
|
66
|
+
* import * as assert from "node:assert"
|
|
67
|
+
*
|
|
68
|
+
* const isString: Predicate.Refinement<unknown, string> = (u): u is string => typeof u === "string"
|
|
69
|
+
*
|
|
70
|
+
* const value: unknown = "hello"
|
|
71
|
+
*
|
|
72
|
+
* if (isString(value)) {
|
|
73
|
+
* // value is now known to be a string
|
|
74
|
+
* assert.strictEqual(value.toUpperCase(), "HELLO")
|
|
75
|
+
* }
|
|
76
|
+
* ```
|
|
77
|
+
*
|
|
25
78
|
* @category models
|
|
26
79
|
* @since 2.0.0
|
|
27
80
|
*/
|
|
@@ -30,16 +83,29 @@ export interface Refinement<in A, out B extends A> {
|
|
|
30
83
|
}
|
|
31
84
|
|
|
32
85
|
/**
|
|
86
|
+
* A namespace for type-level utilities for `Predicate`.
|
|
87
|
+
*
|
|
33
88
|
* @since 3.6.0
|
|
34
89
|
* @category type-level
|
|
35
90
|
*/
|
|
36
91
|
export declare namespace Predicate {
|
|
37
92
|
/**
|
|
93
|
+
* Extracts the input type `A` from a `Predicate<A>`.
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```ts
|
|
97
|
+
* import { type Predicate } from "effect"
|
|
98
|
+
*
|
|
99
|
+
* type T = Predicate.Predicate.In<Predicate.Predicate<string>> // T is string
|
|
100
|
+
* ```
|
|
101
|
+
*
|
|
38
102
|
* @since 3.6.0
|
|
39
103
|
* @category type-level
|
|
40
104
|
*/
|
|
41
105
|
export type In<T extends Any> = [T] extends [Predicate<infer _A>] ? _A : never
|
|
42
106
|
/**
|
|
107
|
+
* A type representing any `Predicate`.
|
|
108
|
+
*
|
|
43
109
|
* @since 3.6.0
|
|
44
110
|
* @category type-level
|
|
45
111
|
*/
|
|
@@ -47,21 +113,45 @@ export declare namespace Predicate {
|
|
|
47
113
|
}
|
|
48
114
|
|
|
49
115
|
/**
|
|
116
|
+
* A namespace for type-level utilities for `Refinement`.
|
|
117
|
+
*
|
|
50
118
|
* @since 3.6.0
|
|
51
119
|
* @category type-level
|
|
52
120
|
*/
|
|
53
121
|
export declare namespace Refinement {
|
|
54
122
|
/**
|
|
123
|
+
* Extracts the input type `A` from a `Refinement<A, B>`.
|
|
124
|
+
*
|
|
125
|
+
* @example
|
|
126
|
+
* ```ts
|
|
127
|
+
* import { type Predicate } from "effect"
|
|
128
|
+
*
|
|
129
|
+
* type IsString = Predicate.Refinement<unknown, string>
|
|
130
|
+
* type T = Predicate.Refinement.In<IsString> // T is unknown
|
|
131
|
+
* ```
|
|
132
|
+
*
|
|
55
133
|
* @since 3.6.0
|
|
56
134
|
* @category type-level
|
|
57
135
|
*/
|
|
58
136
|
export type In<T extends Any> = [T] extends [Refinement<infer _A, infer _>] ? _A : never
|
|
59
137
|
/**
|
|
138
|
+
* Extracts the output (refined) type `B` from a `Refinement<A, B>`.
|
|
139
|
+
*
|
|
140
|
+
* @example
|
|
141
|
+
* ```ts
|
|
142
|
+
* import { type Predicate } from "effect"
|
|
143
|
+
*
|
|
144
|
+
* type IsString = Predicate.Refinement<unknown, string>
|
|
145
|
+
* type T = Predicate.Refinement.Out<IsString> // T is string
|
|
146
|
+
* ```
|
|
147
|
+
*
|
|
60
148
|
* @since 3.6.0
|
|
61
149
|
* @category type-level
|
|
62
150
|
*/
|
|
63
151
|
export type Out<T extends Any> = [T] extends [Refinement<infer _, infer _B>] ? _B : never
|
|
64
152
|
/**
|
|
153
|
+
* A type representing any `Refinement`.
|
|
154
|
+
*
|
|
65
155
|
* @since 3.6.0
|
|
66
156
|
* @category type-level
|
|
67
157
|
*/
|
|
@@ -69,19 +159,26 @@ export declare namespace Refinement {
|
|
|
69
159
|
}
|
|
70
160
|
|
|
71
161
|
/**
|
|
72
|
-
*
|
|
162
|
+
* Transforms a `Predicate<A>` into a `Predicate<B>` by applying a function `(b: B) => A`
|
|
163
|
+
* to the input before passing it to the predicate. This is also known as "contramap" or
|
|
164
|
+
* "pre-composition".
|
|
73
165
|
*
|
|
74
166
|
* @example
|
|
75
167
|
* ```ts
|
|
76
|
-
* import * as assert from "node:assert"
|
|
77
168
|
* import { Predicate, Number } from "effect"
|
|
169
|
+
* import * as assert from "node:assert"
|
|
78
170
|
*
|
|
79
|
-
*
|
|
171
|
+
* // A predicate on numbers
|
|
172
|
+
* const isPositive: Predicate.Predicate<number> = Number.greaterThan(0)
|
|
80
173
|
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
174
|
+
* // A function from `string` to `number`
|
|
175
|
+
* const stringLength = (s: string): number => s.length
|
|
176
|
+
*
|
|
177
|
+
* // Create a new predicate on strings by mapping the input
|
|
178
|
+
* const hasPositiveLength = Predicate.mapInput(isPositive, stringLength)
|
|
179
|
+
*
|
|
180
|
+
* assert.strictEqual(hasPositiveLength("hello"), true)
|
|
181
|
+
* assert.strictEqual(hasPositiveLength(""), false)
|
|
85
182
|
* ```
|
|
86
183
|
*
|
|
87
184
|
* @category combinators
|
|
@@ -89,19 +186,26 @@ export declare namespace Refinement {
|
|
|
89
186
|
*/
|
|
90
187
|
export const mapInput: {
|
|
91
188
|
/**
|
|
92
|
-
*
|
|
189
|
+
* Transforms a `Predicate<A>` into a `Predicate<B>` by applying a function `(b: B) => A`
|
|
190
|
+
* to the input before passing it to the predicate. This is also known as "contramap" or
|
|
191
|
+
* "pre-composition".
|
|
93
192
|
*
|
|
94
193
|
* @example
|
|
95
194
|
* ```ts
|
|
96
|
-
* import * as assert from "node:assert"
|
|
97
195
|
* import { Predicate, Number } from "effect"
|
|
196
|
+
* import * as assert from "node:assert"
|
|
98
197
|
*
|
|
99
|
-
*
|
|
198
|
+
* // A predicate on numbers
|
|
199
|
+
* const isPositive: Predicate.Predicate<number> = Number.greaterThan(0)
|
|
100
200
|
*
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
*
|
|
201
|
+
* // A function from `string` to `number`
|
|
202
|
+
* const stringLength = (s: string): number => s.length
|
|
203
|
+
*
|
|
204
|
+
* // Create a new predicate on strings by mapping the input
|
|
205
|
+
* const hasPositiveLength = Predicate.mapInput(isPositive, stringLength)
|
|
206
|
+
*
|
|
207
|
+
* assert.strictEqual(hasPositiveLength("hello"), true)
|
|
208
|
+
* assert.strictEqual(hasPositiveLength(""), false)
|
|
105
209
|
* ```
|
|
106
210
|
*
|
|
107
211
|
* @category combinators
|
|
@@ -109,19 +213,26 @@ export const mapInput: {
|
|
|
109
213
|
*/
|
|
110
214
|
<B, A>(f: (b: B) => A): (self: Predicate<A>) => Predicate<B>
|
|
111
215
|
/**
|
|
112
|
-
*
|
|
216
|
+
* Transforms a `Predicate<A>` into a `Predicate<B>` by applying a function `(b: B) => A`
|
|
217
|
+
* to the input before passing it to the predicate. This is also known as "contramap" or
|
|
218
|
+
* "pre-composition".
|
|
113
219
|
*
|
|
114
220
|
* @example
|
|
115
221
|
* ```ts
|
|
116
|
-
* import * as assert from "node:assert"
|
|
117
222
|
* import { Predicate, Number } from "effect"
|
|
223
|
+
* import * as assert from "node:assert"
|
|
224
|
+
*
|
|
225
|
+
* // A predicate on numbers
|
|
226
|
+
* const isPositive: Predicate.Predicate<number> = Number.greaterThan(0)
|
|
227
|
+
*
|
|
228
|
+
* // A function from `string` to `number`
|
|
229
|
+
* const stringLength = (s: string): number => s.length
|
|
118
230
|
*
|
|
119
|
-
*
|
|
231
|
+
* // Create a new predicate on strings by mapping the input
|
|
232
|
+
* const hasPositiveLength = Predicate.mapInput(isPositive, stringLength)
|
|
120
233
|
*
|
|
121
|
-
* assert.
|
|
122
|
-
* assert.
|
|
123
|
-
* assert.deepStrictEqual(minLength3("aaa"), true)
|
|
124
|
-
* assert.deepStrictEqual(minLength3("aaaa"), true)
|
|
234
|
+
* assert.strictEqual(hasPositiveLength("hello"), true)
|
|
235
|
+
* assert.strictEqual(hasPositiveLength(""), false)
|
|
125
236
|
* ```
|
|
126
237
|
*
|
|
127
238
|
* @category combinators
|
|
@@ -131,23 +242,24 @@ export const mapInput: {
|
|
|
131
242
|
} = dual(2, <A, B>(self: Predicate<A>, f: (b: B) => A): Predicate<B> => (b) => self(f(b)))
|
|
132
243
|
|
|
133
244
|
/**
|
|
134
|
-
*
|
|
135
|
-
*
|
|
136
|
-
* An `Array` is considered to be a `TupleOf` if its length is exactly `N`.
|
|
245
|
+
* A refinement that checks if a `ReadonlyArray<T>` is a tuple with exactly `N` elements.
|
|
246
|
+
* If the check is successful, the type is narrowed to `TupleOf<N, T>`.
|
|
137
247
|
*
|
|
138
248
|
* @example
|
|
139
249
|
* ```ts
|
|
140
250
|
* import * as assert from "node:assert"
|
|
141
251
|
* import { isTupleOf } from "effect/Predicate"
|
|
142
252
|
*
|
|
143
|
-
*
|
|
144
|
-
*
|
|
145
|
-
* assert.
|
|
253
|
+
* const isTupleOf3 = isTupleOf(3)
|
|
254
|
+
*
|
|
255
|
+
* assert.strictEqual(isTupleOf3([1, 2, 3]), true);
|
|
256
|
+
* assert.strictEqual(isTupleOf3([1, 2]), false);
|
|
146
257
|
*
|
|
147
258
|
* const arr: number[] = [1, 2, 3];
|
|
148
259
|
* if (isTupleOf(arr, 3)) {
|
|
149
|
-
*
|
|
150
|
-
*
|
|
260
|
+
* // The type of arr is now [number, number, number]
|
|
261
|
+
* const [a, b, c] = arr;
|
|
262
|
+
* assert.deepStrictEqual([a, b, c], [1, 2, 3])
|
|
151
263
|
* }
|
|
152
264
|
* ```
|
|
153
265
|
*
|
|
@@ -156,23 +268,24 @@ export const mapInput: {
|
|
|
156
268
|
*/
|
|
157
269
|
export const isTupleOf: {
|
|
158
270
|
/**
|
|
159
|
-
*
|
|
160
|
-
*
|
|
161
|
-
* An `Array` is considered to be a `TupleOf` if its length is exactly `N`.
|
|
271
|
+
* A refinement that checks if a `ReadonlyArray<T>` is a tuple with exactly `N` elements.
|
|
272
|
+
* If the check is successful, the type is narrowed to `TupleOf<N, T>`.
|
|
162
273
|
*
|
|
163
274
|
* @example
|
|
164
275
|
* ```ts
|
|
165
276
|
* import * as assert from "node:assert"
|
|
166
277
|
* import { isTupleOf } from "effect/Predicate"
|
|
167
278
|
*
|
|
168
|
-
*
|
|
169
|
-
*
|
|
170
|
-
* assert.
|
|
279
|
+
* const isTupleOf3 = isTupleOf(3)
|
|
280
|
+
*
|
|
281
|
+
* assert.strictEqual(isTupleOf3([1, 2, 3]), true);
|
|
282
|
+
* assert.strictEqual(isTupleOf3([1, 2]), false);
|
|
171
283
|
*
|
|
172
284
|
* const arr: number[] = [1, 2, 3];
|
|
173
285
|
* if (isTupleOf(arr, 3)) {
|
|
174
|
-
*
|
|
175
|
-
*
|
|
286
|
+
* // The type of arr is now [number, number, number]
|
|
287
|
+
* const [a, b, c] = arr;
|
|
288
|
+
* assert.deepStrictEqual([a, b, c], [1, 2, 3])
|
|
176
289
|
* }
|
|
177
290
|
* ```
|
|
178
291
|
*
|
|
@@ -181,23 +294,24 @@ export const isTupleOf: {
|
|
|
181
294
|
*/
|
|
182
295
|
<N extends number>(n: N): <T>(self: ReadonlyArray<T>) => self is TupleOf<N, T>
|
|
183
296
|
/**
|
|
184
|
-
*
|
|
185
|
-
*
|
|
186
|
-
* An `Array` is considered to be a `TupleOf` if its length is exactly `N`.
|
|
297
|
+
* A refinement that checks if a `ReadonlyArray<T>` is a tuple with exactly `N` elements.
|
|
298
|
+
* If the check is successful, the type is narrowed to `TupleOf<N, T>`.
|
|
187
299
|
*
|
|
188
300
|
* @example
|
|
189
301
|
* ```ts
|
|
190
302
|
* import * as assert from "node:assert"
|
|
191
303
|
* import { isTupleOf } from "effect/Predicate"
|
|
192
304
|
*
|
|
193
|
-
*
|
|
194
|
-
*
|
|
195
|
-
* assert.
|
|
305
|
+
* const isTupleOf3 = isTupleOf(3)
|
|
306
|
+
*
|
|
307
|
+
* assert.strictEqual(isTupleOf3([1, 2, 3]), true);
|
|
308
|
+
* assert.strictEqual(isTupleOf3([1, 2]), false);
|
|
196
309
|
*
|
|
197
310
|
* const arr: number[] = [1, 2, 3];
|
|
198
311
|
* if (isTupleOf(arr, 3)) {
|
|
199
|
-
*
|
|
200
|
-
*
|
|
312
|
+
* // The type of arr is now [number, number, number]
|
|
313
|
+
* const [a, b, c] = arr;
|
|
314
|
+
* assert.deepStrictEqual([a, b, c], [1, 2, 3])
|
|
201
315
|
* }
|
|
202
316
|
* ```
|
|
203
317
|
*
|
|
@@ -208,23 +322,25 @@ export const isTupleOf: {
|
|
|
208
322
|
} = dual(2, <T, N extends number>(self: ReadonlyArray<T>, n: N): self is TupleOf<N, T> => self.length === n)
|
|
209
323
|
|
|
210
324
|
/**
|
|
211
|
-
*
|
|
212
|
-
*
|
|
213
|
-
* An `Array` is considered to be a `TupleOfAtLeast` if its length is at least `N`.
|
|
325
|
+
* A refinement that checks if a `ReadonlyArray<T>` is a tuple with at least `N` elements.
|
|
326
|
+
* If the check is successful, the type is narrowed to `TupleOfAtLeast<N, T>`.
|
|
214
327
|
*
|
|
215
328
|
* @example
|
|
216
329
|
* ```ts
|
|
217
330
|
* import * as assert from "node:assert"
|
|
218
331
|
* import { isTupleOfAtLeast } from "effect/Predicate"
|
|
219
332
|
*
|
|
220
|
-
*
|
|
221
|
-
*
|
|
222
|
-
* assert.
|
|
333
|
+
* const isTupleOfAtLeast3 = isTupleOfAtLeast(3)
|
|
334
|
+
*
|
|
335
|
+
* assert.strictEqual(isTupleOfAtLeast3([1, 2, 3]), true);
|
|
336
|
+
* assert.strictEqual(isTupleOfAtLeast3([1, 2, 3, 4]), true);
|
|
337
|
+
* assert.strictEqual(isTupleOfAtLeast3([1, 2]), false);
|
|
223
338
|
*
|
|
224
339
|
* const arr: number[] = [1, 2, 3, 4];
|
|
225
340
|
* if (isTupleOfAtLeast(arr, 3)) {
|
|
226
|
-
*
|
|
227
|
-
*
|
|
341
|
+
* // The type of arr is now [number, number, number, ...number[]]
|
|
342
|
+
* const [a, b, c] = arr;
|
|
343
|
+
* assert.deepStrictEqual([a, b, c], [1, 2, 3])
|
|
228
344
|
* }
|
|
229
345
|
* ```
|
|
230
346
|
*
|
|
@@ -233,23 +349,25 @@ export const isTupleOf: {
|
|
|
233
349
|
*/
|
|
234
350
|
export const isTupleOfAtLeast: {
|
|
235
351
|
/**
|
|
236
|
-
*
|
|
237
|
-
*
|
|
238
|
-
* An `Array` is considered to be a `TupleOfAtLeast` if its length is at least `N`.
|
|
352
|
+
* A refinement that checks if a `ReadonlyArray<T>` is a tuple with at least `N` elements.
|
|
353
|
+
* If the check is successful, the type is narrowed to `TupleOfAtLeast<N, T>`.
|
|
239
354
|
*
|
|
240
355
|
* @example
|
|
241
356
|
* ```ts
|
|
242
357
|
* import * as assert from "node:assert"
|
|
243
358
|
* import { isTupleOfAtLeast } from "effect/Predicate"
|
|
244
359
|
*
|
|
245
|
-
*
|
|
246
|
-
*
|
|
247
|
-
* assert.
|
|
360
|
+
* const isTupleOfAtLeast3 = isTupleOfAtLeast(3)
|
|
361
|
+
*
|
|
362
|
+
* assert.strictEqual(isTupleOfAtLeast3([1, 2, 3]), true);
|
|
363
|
+
* assert.strictEqual(isTupleOfAtLeast3([1, 2, 3, 4]), true);
|
|
364
|
+
* assert.strictEqual(isTupleOfAtLeast3([1, 2]), false);
|
|
248
365
|
*
|
|
249
366
|
* const arr: number[] = [1, 2, 3, 4];
|
|
250
367
|
* if (isTupleOfAtLeast(arr, 3)) {
|
|
251
|
-
*
|
|
252
|
-
*
|
|
368
|
+
* // The type of arr is now [number, number, number, ...number[]]
|
|
369
|
+
* const [a, b, c] = arr;
|
|
370
|
+
* assert.deepStrictEqual([a, b, c], [1, 2, 3])
|
|
253
371
|
* }
|
|
254
372
|
* ```
|
|
255
373
|
*
|
|
@@ -258,23 +376,25 @@ export const isTupleOfAtLeast: {
|
|
|
258
376
|
*/
|
|
259
377
|
<N extends number>(n: N): <T>(self: ReadonlyArray<T>) => self is TupleOfAtLeast<N, T>
|
|
260
378
|
/**
|
|
261
|
-
*
|
|
262
|
-
*
|
|
263
|
-
* An `Array` is considered to be a `TupleOfAtLeast` if its length is at least `N`.
|
|
379
|
+
* A refinement that checks if a `ReadonlyArray<T>` is a tuple with at least `N` elements.
|
|
380
|
+
* If the check is successful, the type is narrowed to `TupleOfAtLeast<N, T>`.
|
|
264
381
|
*
|
|
265
382
|
* @example
|
|
266
383
|
* ```ts
|
|
267
384
|
* import * as assert from "node:assert"
|
|
268
385
|
* import { isTupleOfAtLeast } from "effect/Predicate"
|
|
269
386
|
*
|
|
270
|
-
*
|
|
271
|
-
*
|
|
272
|
-
* assert.
|
|
387
|
+
* const isTupleOfAtLeast3 = isTupleOfAtLeast(3)
|
|
388
|
+
*
|
|
389
|
+
* assert.strictEqual(isTupleOfAtLeast3([1, 2, 3]), true);
|
|
390
|
+
* assert.strictEqual(isTupleOfAtLeast3([1, 2, 3, 4]), true);
|
|
391
|
+
* assert.strictEqual(isTupleOfAtLeast3([1, 2]), false);
|
|
273
392
|
*
|
|
274
393
|
* const arr: number[] = [1, 2, 3, 4];
|
|
275
394
|
* if (isTupleOfAtLeast(arr, 3)) {
|
|
276
|
-
*
|
|
277
|
-
*
|
|
395
|
+
* // The type of arr is now [number, number, number, ...number[]]
|
|
396
|
+
* const [a, b, c] = arr;
|
|
397
|
+
* assert.deepStrictEqual([a, b, c], [1, 2, 3])
|
|
278
398
|
* }
|
|
279
399
|
* ```
|
|
280
400
|
*
|
|
@@ -285,16 +405,22 @@ export const isTupleOfAtLeast: {
|
|
|
285
405
|
} = dual(2, <T, N extends number>(self: ReadonlyArray<T>, n: N): self is TupleOfAtLeast<N, T> => self.length >= n)
|
|
286
406
|
|
|
287
407
|
/**
|
|
288
|
-
*
|
|
408
|
+
* A predicate that checks if a value is "truthy" in JavaScript.
|
|
409
|
+
* Fails for `false`, `0`, `-0`, `0n`, `""`, `null`, `undefined`, and `NaN`.
|
|
289
410
|
*
|
|
290
411
|
* @example
|
|
291
412
|
* ```ts
|
|
292
413
|
* import * as assert from "node:assert"
|
|
293
414
|
* import { isTruthy } from "effect/Predicate"
|
|
294
415
|
*
|
|
295
|
-
* assert.
|
|
296
|
-
* assert.
|
|
297
|
-
* assert.
|
|
416
|
+
* assert.strictEqual(isTruthy(1), true)
|
|
417
|
+
* assert.strictEqual(isTruthy("hello"), true)
|
|
418
|
+
* assert.strictEqual(isTruthy({}), true)
|
|
419
|
+
*
|
|
420
|
+
* assert.strictEqual(isTruthy(0), false)
|
|
421
|
+
* assert.strictEqual(isTruthy(""), false)
|
|
422
|
+
* assert.strictEqual(isTruthy(null), false)
|
|
423
|
+
* assert.strictEqual(isTruthy(undefined), false)
|
|
298
424
|
* ```
|
|
299
425
|
*
|
|
300
426
|
* @category guards
|
|
@@ -303,18 +429,18 @@ export const isTupleOfAtLeast: {
|
|
|
303
429
|
export const isTruthy = (input: unknown) => !!input
|
|
304
430
|
|
|
305
431
|
/**
|
|
306
|
-
*
|
|
432
|
+
* A refinement that checks if a value is a `Set`.
|
|
307
433
|
*
|
|
308
434
|
* @example
|
|
309
435
|
* ```ts
|
|
310
436
|
* import * as assert from "node:assert"
|
|
311
437
|
* import { isSet } from "effect/Predicate"
|
|
312
438
|
*
|
|
313
|
-
* assert.
|
|
314
|
-
* assert.
|
|
315
|
-
*
|
|
316
|
-
* assert.
|
|
317
|
-
* assert.
|
|
439
|
+
* assert.strictEqual(isSet(new Set([1, 2])), true)
|
|
440
|
+
* assert.strictEqual(isSet(new Set()), true)
|
|
441
|
+
*
|
|
442
|
+
* assert.strictEqual(isSet({}), false)
|
|
443
|
+
* assert.strictEqual(isSet([1, 2]), false)
|
|
318
444
|
* ```
|
|
319
445
|
*
|
|
320
446
|
* @category guards
|
|
@@ -323,17 +449,17 @@ export const isTruthy = (input: unknown) => !!input
|
|
|
323
449
|
export const isSet = (input: unknown): input is Set<unknown> => input instanceof Set
|
|
324
450
|
|
|
325
451
|
/**
|
|
326
|
-
*
|
|
452
|
+
* A refinement that checks if a value is a `Map`.
|
|
327
453
|
*
|
|
328
454
|
* @example
|
|
329
455
|
* ```ts
|
|
330
456
|
* import * as assert from "node:assert"
|
|
331
457
|
* import { isMap } from "effect/Predicate"
|
|
332
458
|
*
|
|
333
|
-
* assert.
|
|
334
|
-
*
|
|
335
|
-
* assert.
|
|
336
|
-
* assert.
|
|
459
|
+
* assert.strictEqual(isMap(new Map()), true)
|
|
460
|
+
*
|
|
461
|
+
* assert.strictEqual(isMap({}), false)
|
|
462
|
+
* assert.strictEqual(isMap(new Set()), false)
|
|
337
463
|
* ```
|
|
338
464
|
*
|
|
339
465
|
* @category guards
|
|
@@ -342,16 +468,18 @@ export const isSet = (input: unknown): input is Set<unknown> => input instanceof
|
|
|
342
468
|
export const isMap = (input: unknown): input is Map<unknown, unknown> => input instanceof Map
|
|
343
469
|
|
|
344
470
|
/**
|
|
345
|
-
*
|
|
471
|
+
* A refinement that checks if a value is a `string`.
|
|
346
472
|
*
|
|
347
473
|
* @example
|
|
348
474
|
* ```ts
|
|
349
475
|
* import * as assert from "node:assert"
|
|
350
476
|
* import { isString } from "effect/Predicate"
|
|
351
477
|
*
|
|
352
|
-
* assert.
|
|
478
|
+
* assert.strictEqual(isString("hello"), true)
|
|
479
|
+
* assert.strictEqual(isString(""), true)
|
|
353
480
|
*
|
|
354
|
-
* assert.
|
|
481
|
+
* assert.strictEqual(isString(123), false)
|
|
482
|
+
* assert.strictEqual(isString(null), false)
|
|
355
483
|
* ```
|
|
356
484
|
*
|
|
357
485
|
* @category guards
|
|
@@ -360,16 +488,20 @@ export const isMap = (input: unknown): input is Map<unknown, unknown> => input i
|
|
|
360
488
|
export const isString = (input: unknown): input is string => typeof input === "string"
|
|
361
489
|
|
|
362
490
|
/**
|
|
363
|
-
*
|
|
491
|
+
* A refinement that checks if a value is a `number`. Note that this
|
|
492
|
+
* check returns `false` for `NaN`.
|
|
364
493
|
*
|
|
365
494
|
* @example
|
|
366
495
|
* ```ts
|
|
367
496
|
* import * as assert from "node:assert"
|
|
368
497
|
* import { isNumber } from "effect/Predicate"
|
|
369
498
|
*
|
|
370
|
-
* assert.
|
|
499
|
+
* assert.strictEqual(isNumber(123), true)
|
|
500
|
+
* assert.strictEqual(isNumber(0), true)
|
|
501
|
+
* assert.strictEqual(isNumber(-1.5), true)
|
|
371
502
|
*
|
|
372
|
-
* assert.
|
|
503
|
+
* assert.strictEqual(isNumber("123"), false)
|
|
504
|
+
* assert.strictEqual(isNumber(NaN), false) // Special case: NaN is a number type but returns false
|
|
373
505
|
* ```
|
|
374
506
|
*
|
|
375
507
|
* @category guards
|
|
@@ -378,16 +510,18 @@ export const isString = (input: unknown): input is string => typeof input === "s
|
|
|
378
510
|
export const isNumber = (input: unknown): input is number => typeof input === "number"
|
|
379
511
|
|
|
380
512
|
/**
|
|
381
|
-
*
|
|
513
|
+
* A refinement that checks if a value is a `boolean`.
|
|
382
514
|
*
|
|
383
515
|
* @example
|
|
384
516
|
* ```ts
|
|
385
517
|
* import * as assert from "node:assert"
|
|
386
518
|
* import { isBoolean } from "effect/Predicate"
|
|
387
519
|
*
|
|
388
|
-
* assert.
|
|
520
|
+
* assert.strictEqual(isBoolean(true), true)
|
|
521
|
+
* assert.strictEqual(isBoolean(false), true)
|
|
389
522
|
*
|
|
390
|
-
* assert.
|
|
523
|
+
* assert.strictEqual(isBoolean("true"), false)
|
|
524
|
+
* assert.strictEqual(isBoolean(0), false)
|
|
391
525
|
* ```
|
|
392
526
|
*
|
|
393
527
|
* @category guards
|
|
@@ -396,16 +530,17 @@ export const isNumber = (input: unknown): input is number => typeof input === "n
|
|
|
396
530
|
export const isBoolean = (input: unknown): input is boolean => typeof input === "boolean"
|
|
397
531
|
|
|
398
532
|
/**
|
|
399
|
-
*
|
|
533
|
+
* A refinement that checks if a value is a `bigint`.
|
|
400
534
|
*
|
|
401
535
|
* @example
|
|
402
536
|
* ```ts
|
|
403
537
|
* import * as assert from "node:assert"
|
|
404
538
|
* import { isBigInt } from "effect/Predicate"
|
|
405
539
|
*
|
|
406
|
-
* assert.
|
|
540
|
+
* assert.strictEqual(isBigInt(1n), true)
|
|
407
541
|
*
|
|
408
|
-
* assert.
|
|
542
|
+
* assert.strictEqual(isBigInt(1), false)
|
|
543
|
+
* assert.strictEqual(isBigInt("1"), false)
|
|
409
544
|
* ```
|
|
410
545
|
*
|
|
411
546
|
* @category guards
|
|
@@ -414,16 +549,16 @@ export const isBoolean = (input: unknown): input is boolean => typeof input ===
|
|
|
414
549
|
export const isBigInt = (input: unknown): input is bigint => typeof input === "bigint"
|
|
415
550
|
|
|
416
551
|
/**
|
|
417
|
-
*
|
|
552
|
+
* A refinement that checks if a value is a `symbol`.
|
|
418
553
|
*
|
|
419
554
|
* @example
|
|
420
555
|
* ```ts
|
|
421
556
|
* import * as assert from "node:assert"
|
|
422
557
|
* import { isSymbol } from "effect/Predicate"
|
|
423
558
|
*
|
|
424
|
-
* assert.
|
|
559
|
+
* assert.strictEqual(isSymbol(Symbol.for("a")), true)
|
|
425
560
|
*
|
|
426
|
-
* assert.
|
|
561
|
+
* assert.strictEqual(isSymbol("a"), false)
|
|
427
562
|
* ```
|
|
428
563
|
*
|
|
429
564
|
* @category guards
|
|
@@ -432,20 +567,24 @@ export const isBigInt = (input: unknown): input is bigint => typeof input === "b
|
|
|
432
567
|
export const isSymbol = (input: unknown): input is symbol => typeof input === "symbol"
|
|
433
568
|
|
|
434
569
|
// TODO: make public
|
|
435
|
-
/**
|
|
570
|
+
/**
|
|
571
|
+
* A refinement that checks if a value is a valid `PropertyKey` (a `string`, `number`, or `symbol`).
|
|
572
|
+
* @internal
|
|
573
|
+
*/
|
|
436
574
|
export const isPropertyKey = (u: unknown): u is PropertyKey => isString(u) || isNumber(u) || isSymbol(u)
|
|
437
575
|
|
|
438
576
|
/**
|
|
439
|
-
*
|
|
577
|
+
* A refinement that checks if a value is a `Function`.
|
|
440
578
|
*
|
|
441
579
|
* @example
|
|
442
580
|
* ```ts
|
|
443
581
|
* import * as assert from "node:assert"
|
|
444
582
|
* import { isFunction } from "effect/Predicate"
|
|
445
583
|
*
|
|
446
|
-
* assert.
|
|
584
|
+
* assert.strictEqual(isFunction(() => {}), true)
|
|
585
|
+
* assert.strictEqual(isFunction(isFunction), true)
|
|
447
586
|
*
|
|
448
|
-
* assert.
|
|
587
|
+
* assert.strictEqual(isFunction("function"), false)
|
|
449
588
|
* ```
|
|
450
589
|
*
|
|
451
590
|
* @category guards
|
|
@@ -454,17 +593,17 @@ export const isPropertyKey = (u: unknown): u is PropertyKey => isString(u) || is
|
|
|
454
593
|
export const isFunction: (input: unknown) => input is Function = isFunction_
|
|
455
594
|
|
|
456
595
|
/**
|
|
457
|
-
*
|
|
596
|
+
* A refinement that checks if a value is `undefined`.
|
|
458
597
|
*
|
|
459
598
|
* @example
|
|
460
599
|
* ```ts
|
|
461
600
|
* import * as assert from "node:assert"
|
|
462
601
|
* import { isUndefined } from "effect/Predicate"
|
|
463
602
|
*
|
|
464
|
-
* assert.
|
|
603
|
+
* assert.strictEqual(isUndefined(undefined), true)
|
|
465
604
|
*
|
|
466
|
-
* assert.
|
|
467
|
-
* assert.
|
|
605
|
+
* assert.strictEqual(isUndefined(null), false)
|
|
606
|
+
* assert.strictEqual(isUndefined("undefined"), false)
|
|
468
607
|
* ```
|
|
469
608
|
*
|
|
470
609
|
* @category guards
|
|
@@ -473,17 +612,17 @@ export const isFunction: (input: unknown) => input is Function = isFunction_
|
|
|
473
612
|
export const isUndefined = (input: unknown): input is undefined => input === undefined
|
|
474
613
|
|
|
475
614
|
/**
|
|
476
|
-
*
|
|
615
|
+
* A refinement that checks if a value is not `undefined`.
|
|
477
616
|
*
|
|
478
617
|
* @example
|
|
479
618
|
* ```ts
|
|
480
619
|
* import * as assert from "node:assert"
|
|
481
620
|
* import { isNotUndefined } from "effect/Predicate"
|
|
482
621
|
*
|
|
483
|
-
* assert.
|
|
484
|
-
* assert.
|
|
622
|
+
* assert.strictEqual(isNotUndefined(null), true)
|
|
623
|
+
* assert.strictEqual(isNotUndefined("value"), true)
|
|
485
624
|
*
|
|
486
|
-
* assert.
|
|
625
|
+
* assert.strictEqual(isNotUndefined(undefined), false)
|
|
487
626
|
* ```
|
|
488
627
|
*
|
|
489
628
|
* @category guards
|
|
@@ -492,17 +631,17 @@ export const isUndefined = (input: unknown): input is undefined => input === und
|
|
|
492
631
|
export const isNotUndefined = <A>(input: A): input is Exclude<A, undefined> => input !== undefined
|
|
493
632
|
|
|
494
633
|
/**
|
|
495
|
-
*
|
|
634
|
+
* A refinement that checks if a value is `null`.
|
|
496
635
|
*
|
|
497
636
|
* @example
|
|
498
637
|
* ```ts
|
|
499
638
|
* import * as assert from "node:assert"
|
|
500
639
|
* import { isNull } from "effect/Predicate"
|
|
501
640
|
*
|
|
502
|
-
* assert.
|
|
641
|
+
* assert.strictEqual(isNull(null), true)
|
|
503
642
|
*
|
|
504
|
-
* assert.
|
|
505
|
-
* assert.
|
|
643
|
+
* assert.strictEqual(isNull(undefined), false)
|
|
644
|
+
* assert.strictEqual(isNull("null"), false)
|
|
506
645
|
* ```
|
|
507
646
|
*
|
|
508
647
|
* @category guards
|
|
@@ -511,17 +650,17 @@ export const isNotUndefined = <A>(input: A): input is Exclude<A, undefined> => i
|
|
|
511
650
|
export const isNull = (input: unknown): input is null => input === null
|
|
512
651
|
|
|
513
652
|
/**
|
|
514
|
-
*
|
|
653
|
+
* A refinement that checks if a value is not `null`.
|
|
515
654
|
*
|
|
516
655
|
* @example
|
|
517
656
|
* ```ts
|
|
518
657
|
* import * as assert from "node:assert"
|
|
519
658
|
* import { isNotNull } from "effect/Predicate"
|
|
520
659
|
*
|
|
521
|
-
* assert.
|
|
522
|
-
* assert.
|
|
660
|
+
* assert.strictEqual(isNotNull(undefined), true)
|
|
661
|
+
* assert.strictEqual(isNotNull("value"), true)
|
|
523
662
|
*
|
|
524
|
-
* assert.
|
|
663
|
+
* assert.strictEqual(isNotNull(null), false)
|
|
525
664
|
* ```
|
|
526
665
|
*
|
|
527
666
|
* @category guards
|
|
@@ -530,17 +669,16 @@ export const isNull = (input: unknown): input is null => input === null
|
|
|
530
669
|
export const isNotNull = <A>(input: A): input is Exclude<A, null> => input !== null
|
|
531
670
|
|
|
532
671
|
/**
|
|
533
|
-
* A
|
|
672
|
+
* A refinement that always returns `false`. The type is narrowed to `never`.
|
|
534
673
|
*
|
|
535
674
|
* @example
|
|
536
675
|
* ```ts
|
|
537
676
|
* import * as assert from "node:assert"
|
|
538
677
|
* import { isNever } from "effect/Predicate"
|
|
539
678
|
*
|
|
540
|
-
* assert.
|
|
541
|
-
* assert.
|
|
542
|
-
* assert.
|
|
543
|
-
* assert.deepStrictEqual(isNever([]), false)
|
|
679
|
+
* assert.strictEqual(isNever(1), false)
|
|
680
|
+
* assert.strictEqual(isNever(null), false)
|
|
681
|
+
* assert.strictEqual(isNever({}), false)
|
|
544
682
|
* ```
|
|
545
683
|
*
|
|
546
684
|
* @category guards
|
|
@@ -549,18 +687,16 @@ export const isNotNull = <A>(input: A): input is Exclude<A, null> => input !== n
|
|
|
549
687
|
export const isNever: (input: unknown) => input is never = (_: unknown): _ is never => false
|
|
550
688
|
|
|
551
689
|
/**
|
|
552
|
-
* A
|
|
690
|
+
* A refinement that always returns `true`. The type is narrowed to `unknown`.
|
|
553
691
|
*
|
|
554
692
|
* @example
|
|
555
693
|
* ```ts
|
|
556
694
|
* import * as assert from "node:assert"
|
|
557
695
|
* import { isUnknown } from "effect/Predicate"
|
|
558
696
|
*
|
|
559
|
-
* assert.
|
|
560
|
-
* assert.
|
|
561
|
-
*
|
|
562
|
-
* assert.deepStrictEqual(isUnknown({}), true)
|
|
563
|
-
* assert.deepStrictEqual(isUnknown([]), true)
|
|
697
|
+
* assert.strictEqual(isUnknown(1), true)
|
|
698
|
+
* assert.strictEqual(isUnknown(null), true)
|
|
699
|
+
* assert.strictEqual(isUnknown({}), true)
|
|
564
700
|
* ```
|
|
565
701
|
*
|
|
566
702
|
* @category guards
|
|
@@ -568,46 +704,100 @@ export const isNever: (input: unknown) => input is never = (_: unknown): _ is ne
|
|
|
568
704
|
*/
|
|
569
705
|
export const isUnknown: (input: unknown) => input is unknown = (_): _ is unknown => true
|
|
570
706
|
|
|
571
|
-
/**
|
|
707
|
+
/**
|
|
708
|
+
* Checks if the input is an object or an array.
|
|
709
|
+
* @internal
|
|
710
|
+
*/
|
|
572
711
|
export const isRecordOrArray = (input: unknown): input is { [x: PropertyKey]: unknown } =>
|
|
573
712
|
typeof input === "object" && input !== null
|
|
574
713
|
|
|
575
714
|
/**
|
|
576
|
-
*
|
|
715
|
+
* A refinement that checks if a value is an `object`. Note that in JavaScript,
|
|
716
|
+
* arrays and functions are also considered objects.
|
|
577
717
|
*
|
|
578
718
|
* @example
|
|
579
719
|
* ```ts
|
|
580
720
|
* import * as assert from "node:assert"
|
|
581
721
|
* import { isObject } from "effect/Predicate"
|
|
582
722
|
*
|
|
583
|
-
* assert.
|
|
584
|
-
* assert.
|
|
723
|
+
* assert.strictEqual(isObject({}), true)
|
|
724
|
+
* assert.strictEqual(isObject([]), true)
|
|
725
|
+
* assert.strictEqual(isObject(() => {}), true)
|
|
585
726
|
*
|
|
586
|
-
* assert.
|
|
587
|
-
* assert.
|
|
727
|
+
* assert.strictEqual(isObject(null), false)
|
|
728
|
+
* assert.strictEqual(isObject("hello"), false)
|
|
588
729
|
* ```
|
|
589
730
|
*
|
|
590
731
|
* @category guards
|
|
591
732
|
* @since 2.0.0
|
|
733
|
+
* @see isRecord to check for plain objects (excluding arrays and functions).
|
|
592
734
|
*/
|
|
593
735
|
export const isObject = (input: unknown): input is object => isRecordOrArray(input) || isFunction(input)
|
|
594
736
|
|
|
595
737
|
/**
|
|
596
|
-
*
|
|
738
|
+
* A refinement that checks if a value is an object-like value and has a specific property key.
|
|
739
|
+
*
|
|
740
|
+
* @example
|
|
741
|
+
* ```ts
|
|
742
|
+
* import * as assert from "node:assert"
|
|
743
|
+
* import { hasProperty } from "effect/Predicate"
|
|
744
|
+
*
|
|
745
|
+
* assert.strictEqual(hasProperty({ a: 1 }, "a"), true)
|
|
746
|
+
* assert.strictEqual(hasProperty({ a: 1 }, "b"), false)
|
|
747
|
+
*
|
|
748
|
+
* const value: unknown = { name: "Alice" };
|
|
749
|
+
* if (hasProperty(value, "name")) {
|
|
750
|
+
* // The type of `value` is narrowed to `{ name: unknown }`
|
|
751
|
+
* // and we can safely access `value.name`
|
|
752
|
+
* console.log(value.name)
|
|
753
|
+
* }
|
|
754
|
+
* ```
|
|
597
755
|
*
|
|
598
756
|
* @category guards
|
|
599
757
|
* @since 2.0.0
|
|
600
758
|
*/
|
|
601
759
|
export const hasProperty: {
|
|
602
760
|
/**
|
|
603
|
-
*
|
|
761
|
+
* A refinement that checks if a value is an object-like value and has a specific property key.
|
|
762
|
+
*
|
|
763
|
+
* @example
|
|
764
|
+
* ```ts
|
|
765
|
+
* import * as assert from "node:assert"
|
|
766
|
+
* import { hasProperty } from "effect/Predicate"
|
|
767
|
+
*
|
|
768
|
+
* assert.strictEqual(hasProperty({ a: 1 }, "a"), true)
|
|
769
|
+
* assert.strictEqual(hasProperty({ a: 1 }, "b"), false)
|
|
770
|
+
*
|
|
771
|
+
* const value: unknown = { name: "Alice" };
|
|
772
|
+
* if (hasProperty(value, "name")) {
|
|
773
|
+
* // The type of `value` is narrowed to `{ name: unknown }`
|
|
774
|
+
* // and we can safely access `value.name`
|
|
775
|
+
* console.log(value.name)
|
|
776
|
+
* }
|
|
777
|
+
* ```
|
|
604
778
|
*
|
|
605
779
|
* @category guards
|
|
606
780
|
* @since 2.0.0
|
|
607
781
|
*/
|
|
608
782
|
<P extends PropertyKey>(property: P): (self: unknown) => self is { [K in P]: unknown }
|
|
609
783
|
/**
|
|
610
|
-
*
|
|
784
|
+
* A refinement that checks if a value is an object-like value and has a specific property key.
|
|
785
|
+
*
|
|
786
|
+
* @example
|
|
787
|
+
* ```ts
|
|
788
|
+
* import * as assert from "node:assert"
|
|
789
|
+
* import { hasProperty } from "effect/Predicate"
|
|
790
|
+
*
|
|
791
|
+
* assert.strictEqual(hasProperty({ a: 1 }, "a"), true)
|
|
792
|
+
* assert.strictEqual(hasProperty({ a: 1 }, "b"), false)
|
|
793
|
+
*
|
|
794
|
+
* const value: unknown = { name: "Alice" };
|
|
795
|
+
* if (hasProperty(value, "name")) {
|
|
796
|
+
* // The type of `value` is narrowed to `{ name: unknown }`
|
|
797
|
+
* // and we can safely access `value.name`
|
|
798
|
+
* console.log(value.name)
|
|
799
|
+
* }
|
|
800
|
+
* ```
|
|
611
801
|
*
|
|
612
802
|
* @category guards
|
|
613
803
|
* @since 2.0.0
|
|
@@ -620,19 +810,29 @@ export const hasProperty: {
|
|
|
620
810
|
)
|
|
621
811
|
|
|
622
812
|
/**
|
|
623
|
-
*
|
|
813
|
+
* A refinement that checks if a value is an object with a `_tag` property
|
|
814
|
+
* that matches the given tag. This is a powerful tool for working with
|
|
815
|
+
* discriminated union types.
|
|
624
816
|
*
|
|
625
817
|
* @example
|
|
626
818
|
* ```ts
|
|
627
819
|
* import * as assert from "node:assert"
|
|
628
820
|
* import { isTagged } from "effect/Predicate"
|
|
629
821
|
*
|
|
630
|
-
*
|
|
631
|
-
*
|
|
632
|
-
*
|
|
633
|
-
*
|
|
634
|
-
*
|
|
635
|
-
*
|
|
822
|
+
* type Shape = { _tag: "circle"; radius: number } | { _tag: "square"; side: number }
|
|
823
|
+
*
|
|
824
|
+
* const isCircle = isTagged("circle")
|
|
825
|
+
*
|
|
826
|
+
* const shape1: Shape = { _tag: "circle", radius: 10 }
|
|
827
|
+
* const shape2: Shape = { _tag: "square", side: 5 }
|
|
828
|
+
*
|
|
829
|
+
* assert.strictEqual(isCircle(shape1), true)
|
|
830
|
+
* assert.strictEqual(isCircle(shape2), false)
|
|
831
|
+
*
|
|
832
|
+
* if (isCircle(shape1)) {
|
|
833
|
+
* // shape1 is now narrowed to { _tag: "circle"; radius: number }
|
|
834
|
+
* assert.strictEqual(shape1.radius, 10)
|
|
835
|
+
* }
|
|
636
836
|
* ```
|
|
637
837
|
*
|
|
638
838
|
* @category guards
|
|
@@ -640,19 +840,29 @@ export const hasProperty: {
|
|
|
640
840
|
*/
|
|
641
841
|
export const isTagged: {
|
|
642
842
|
/**
|
|
643
|
-
*
|
|
843
|
+
* A refinement that checks if a value is an object with a `_tag` property
|
|
844
|
+
* that matches the given tag. This is a powerful tool for working with
|
|
845
|
+
* discriminated union types.
|
|
644
846
|
*
|
|
645
847
|
* @example
|
|
646
848
|
* ```ts
|
|
647
849
|
* import * as assert from "node:assert"
|
|
648
850
|
* import { isTagged } from "effect/Predicate"
|
|
649
851
|
*
|
|
650
|
-
*
|
|
651
|
-
*
|
|
652
|
-
*
|
|
653
|
-
*
|
|
654
|
-
*
|
|
655
|
-
*
|
|
852
|
+
* type Shape = { _tag: "circle"; radius: number } | { _tag: "square"; side: number }
|
|
853
|
+
*
|
|
854
|
+
* const isCircle = isTagged("circle")
|
|
855
|
+
*
|
|
856
|
+
* const shape1: Shape = { _tag: "circle", radius: 10 }
|
|
857
|
+
* const shape2: Shape = { _tag: "square", side: 5 }
|
|
858
|
+
*
|
|
859
|
+
* assert.strictEqual(isCircle(shape1), true)
|
|
860
|
+
* assert.strictEqual(isCircle(shape2), false)
|
|
861
|
+
*
|
|
862
|
+
* if (isCircle(shape1)) {
|
|
863
|
+
* // shape1 is now narrowed to { _tag: "circle"; radius: number }
|
|
864
|
+
* assert.strictEqual(shape1.radius, 10)
|
|
865
|
+
* }
|
|
656
866
|
* ```
|
|
657
867
|
*
|
|
658
868
|
* @category guards
|
|
@@ -660,19 +870,29 @@ export const isTagged: {
|
|
|
660
870
|
*/
|
|
661
871
|
<K extends string>(tag: K): (self: unknown) => self is { _tag: K }
|
|
662
872
|
/**
|
|
663
|
-
*
|
|
873
|
+
* A refinement that checks if a value is an object with a `_tag` property
|
|
874
|
+
* that matches the given tag. This is a powerful tool for working with
|
|
875
|
+
* discriminated union types.
|
|
664
876
|
*
|
|
665
877
|
* @example
|
|
666
878
|
* ```ts
|
|
667
879
|
* import * as assert from "node:assert"
|
|
668
880
|
* import { isTagged } from "effect/Predicate"
|
|
669
881
|
*
|
|
670
|
-
*
|
|
671
|
-
*
|
|
672
|
-
*
|
|
673
|
-
*
|
|
674
|
-
*
|
|
675
|
-
*
|
|
882
|
+
* type Shape = { _tag: "circle"; radius: number } | { _tag: "square"; side: number }
|
|
883
|
+
*
|
|
884
|
+
* const isCircle = isTagged("circle")
|
|
885
|
+
*
|
|
886
|
+
* const shape1: Shape = { _tag: "circle", radius: 10 }
|
|
887
|
+
* const shape2: Shape = { _tag: "square", side: 5 }
|
|
888
|
+
*
|
|
889
|
+
* assert.strictEqual(isCircle(shape1), true)
|
|
890
|
+
* assert.strictEqual(isCircle(shape2), false)
|
|
891
|
+
*
|
|
892
|
+
* if (isCircle(shape1)) {
|
|
893
|
+
* // shape1 is now narrowed to { _tag: "circle"; radius: number }
|
|
894
|
+
* assert.strictEqual(shape1.radius, 10)
|
|
895
|
+
* }
|
|
676
896
|
* ```
|
|
677
897
|
*
|
|
678
898
|
* @category guards
|
|
@@ -685,57 +905,61 @@ export const isTagged: {
|
|
|
685
905
|
)
|
|
686
906
|
|
|
687
907
|
/**
|
|
688
|
-
* A
|
|
908
|
+
* A refinement that checks if a value is either `null` or `undefined`.
|
|
689
909
|
*
|
|
690
910
|
* @example
|
|
691
911
|
* ```ts
|
|
692
912
|
* import * as assert from "node:assert"
|
|
693
913
|
* import { isNullable } from "effect/Predicate"
|
|
694
914
|
*
|
|
695
|
-
* assert.
|
|
696
|
-
* assert.
|
|
915
|
+
* assert.strictEqual(isNullable(null), true)
|
|
916
|
+
* assert.strictEqual(isNullable(undefined), true)
|
|
697
917
|
*
|
|
698
|
-
* assert.
|
|
699
|
-
* assert.
|
|
918
|
+
* assert.strictEqual(isNullable(0), false)
|
|
919
|
+
* assert.strictEqual(isNullable(""), false)
|
|
700
920
|
* ```
|
|
701
921
|
*
|
|
702
922
|
* @category guards
|
|
703
923
|
* @since 2.0.0
|
|
924
|
+
* @see isNotNullable
|
|
704
925
|
*/
|
|
705
926
|
export const isNullable = <A>(input: A): input is Extract<A, null | undefined> => input === null || input === undefined
|
|
706
927
|
|
|
707
928
|
/**
|
|
708
|
-
* A
|
|
929
|
+
* A refinement that checks if a value is neither `null` nor `undefined`.
|
|
930
|
+
* The type is narrowed to `NonNullable<A>`.
|
|
709
931
|
*
|
|
710
932
|
* @example
|
|
711
933
|
* ```ts
|
|
712
934
|
* import * as assert from "node:assert"
|
|
713
935
|
* import { isNotNullable } from "effect/Predicate"
|
|
714
936
|
*
|
|
715
|
-
* assert.
|
|
716
|
-
* assert.
|
|
937
|
+
* assert.strictEqual(isNotNullable(0), true)
|
|
938
|
+
* assert.strictEqual(isNotNullable("hello"), true)
|
|
717
939
|
*
|
|
718
|
-
* assert.
|
|
719
|
-
* assert.
|
|
940
|
+
* assert.strictEqual(isNotNullable(null), false)
|
|
941
|
+
* assert.strictEqual(isNotNullable(undefined), false)
|
|
720
942
|
* ```
|
|
721
943
|
*
|
|
722
944
|
* @category guards
|
|
723
945
|
* @since 2.0.0
|
|
946
|
+
* @see isNullable
|
|
724
947
|
*/
|
|
725
948
|
export const isNotNullable = <A>(input: A): input is NonNullable<A> => input !== null && input !== undefined
|
|
726
949
|
|
|
727
950
|
/**
|
|
728
|
-
* A
|
|
951
|
+
* A refinement that checks if a value is an instance of `Error`.
|
|
729
952
|
*
|
|
730
953
|
* @example
|
|
731
954
|
* ```ts
|
|
732
955
|
* import * as assert from "node:assert"
|
|
733
956
|
* import { isError } from "effect/Predicate"
|
|
734
957
|
*
|
|
735
|
-
* assert.
|
|
958
|
+
* assert.strictEqual(isError(new Error("boom")), true)
|
|
959
|
+
* assert.strictEqual(isError(new TypeError("boom")), true)
|
|
736
960
|
*
|
|
737
|
-
* assert.
|
|
738
|
-
* assert.
|
|
961
|
+
* assert.strictEqual(isError({ message: "boom" }), false)
|
|
962
|
+
* assert.strictEqual(isError("boom"), false)
|
|
739
963
|
* ```
|
|
740
964
|
*
|
|
741
965
|
* @category guards
|
|
@@ -744,17 +968,17 @@ export const isNotNullable = <A>(input: A): input is NonNullable<A> => input !==
|
|
|
744
968
|
export const isError = (input: unknown): input is Error => input instanceof Error
|
|
745
969
|
|
|
746
970
|
/**
|
|
747
|
-
* A
|
|
971
|
+
* A refinement that checks if a value is a `Uint8Array`.
|
|
748
972
|
*
|
|
749
973
|
* @example
|
|
750
974
|
* ```ts
|
|
751
975
|
* import * as assert from "node:assert"
|
|
752
976
|
* import { isUint8Array } from "effect/Predicate"
|
|
753
977
|
*
|
|
754
|
-
* assert.
|
|
978
|
+
* assert.strictEqual(isUint8Array(new Uint8Array()), true)
|
|
755
979
|
*
|
|
756
|
-
* assert.
|
|
757
|
-
* assert.
|
|
980
|
+
* assert.strictEqual(isUint8Array(new Uint16Array()), false)
|
|
981
|
+
* assert.strictEqual(isUint8Array([1, 2, 3]), false)
|
|
758
982
|
* ```
|
|
759
983
|
*
|
|
760
984
|
* @category guards
|
|
@@ -763,17 +987,17 @@ export const isError = (input: unknown): input is Error => input instanceof Erro
|
|
|
763
987
|
export const isUint8Array = (input: unknown): input is Uint8Array => input instanceof Uint8Array
|
|
764
988
|
|
|
765
989
|
/**
|
|
766
|
-
* A
|
|
990
|
+
* A refinement that checks if a value is a `Date` object.
|
|
767
991
|
*
|
|
768
992
|
* @example
|
|
769
993
|
* ```ts
|
|
770
994
|
* import * as assert from "node:assert"
|
|
771
995
|
* import { isDate } from "effect/Predicate"
|
|
772
996
|
*
|
|
773
|
-
* assert.
|
|
997
|
+
* assert.strictEqual(isDate(new Date()), true)
|
|
774
998
|
*
|
|
775
|
-
* assert.
|
|
776
|
-
* assert.
|
|
999
|
+
* assert.strictEqual(isDate(Date.now()), false) // `Date.now()` returns a number
|
|
1000
|
+
* assert.strictEqual(isDate("2023-01-01"), false)
|
|
777
1001
|
* ```
|
|
778
1002
|
*
|
|
779
1003
|
* @category guards
|
|
@@ -782,18 +1006,20 @@ export const isUint8Array = (input: unknown): input is Uint8Array => input insta
|
|
|
782
1006
|
export const isDate = (input: unknown): input is Date => input instanceof Date
|
|
783
1007
|
|
|
784
1008
|
/**
|
|
785
|
-
* A
|
|
1009
|
+
* A refinement that checks if a value is an `Iterable`.
|
|
1010
|
+
* Many built-in types are iterable, such as `Array`, `string`, `Map`, and `Set`.
|
|
786
1011
|
*
|
|
787
1012
|
* @example
|
|
788
1013
|
* ```ts
|
|
789
1014
|
* import * as assert from "node:assert"
|
|
790
1015
|
* import { isIterable } from "effect/Predicate"
|
|
791
1016
|
*
|
|
792
|
-
* assert.
|
|
793
|
-
* assert.
|
|
1017
|
+
* assert.strictEqual(isIterable([]), true)
|
|
1018
|
+
* assert.strictEqual(isIterable("hello"), true)
|
|
1019
|
+
* assert.strictEqual(isIterable(new Set()), true)
|
|
794
1020
|
*
|
|
795
|
-
* assert.
|
|
796
|
-
* assert.
|
|
1021
|
+
* assert.strictEqual(isIterable({}), false)
|
|
1022
|
+
* assert.strictEqual(isIterable(123), false)
|
|
797
1023
|
* ```
|
|
798
1024
|
*
|
|
799
1025
|
* @category guards
|
|
@@ -802,44 +1028,46 @@ export const isDate = (input: unknown): input is Date => input instanceof Date
|
|
|
802
1028
|
export const isIterable = (input: unknown): input is Iterable<unknown> => hasProperty(input, Symbol.iterator)
|
|
803
1029
|
|
|
804
1030
|
/**
|
|
805
|
-
* A
|
|
1031
|
+
* A refinement that checks if a value is a record (i.e., a plain object).
|
|
1032
|
+
* This check returns `false` for arrays, `null`, and functions.
|
|
806
1033
|
*
|
|
807
1034
|
* @example
|
|
808
1035
|
* ```ts
|
|
809
1036
|
* import * as assert from "node:assert"
|
|
810
1037
|
* import { isRecord } from "effect/Predicate"
|
|
811
1038
|
*
|
|
812
|
-
* assert.
|
|
813
|
-
* assert.
|
|
1039
|
+
* assert.strictEqual(isRecord({}), true)
|
|
1040
|
+
* assert.strictEqual(isRecord({ a: 1 }), true)
|
|
814
1041
|
*
|
|
815
|
-
* assert.
|
|
816
|
-
* assert.
|
|
817
|
-
* assert.
|
|
818
|
-
* assert.
|
|
819
|
-
* assert.deepStrictEqual(isRecord(() => null), false)
|
|
1042
|
+
* assert.strictEqual(isRecord([]), false)
|
|
1043
|
+
* assert.strictEqual(isRecord(new Date()), false)
|
|
1044
|
+
* assert.strictEqual(isRecord(null), false)
|
|
1045
|
+
* assert.strictEqual(isRecord(() => null), false)
|
|
820
1046
|
* ```
|
|
821
1047
|
*
|
|
822
1048
|
* @category guards
|
|
823
1049
|
* @since 2.0.0
|
|
1050
|
+
* @see isObject
|
|
824
1051
|
*/
|
|
825
1052
|
export const isRecord = (input: unknown): input is { [x: string | symbol]: unknown } =>
|
|
826
1053
|
isRecordOrArray(input) && !Array.isArray(input)
|
|
827
1054
|
|
|
828
1055
|
/**
|
|
829
|
-
* A
|
|
1056
|
+
* A refinement that checks if a value is a readonly record (i.e., a plain object).
|
|
1057
|
+
* This check returns `false` for arrays, `null`, and functions.
|
|
1058
|
+
*
|
|
1059
|
+
* This is an alias for `isRecord`.
|
|
830
1060
|
*
|
|
831
1061
|
* @example
|
|
832
1062
|
* ```ts
|
|
833
1063
|
* import * as assert from "node:assert"
|
|
834
1064
|
* import { isReadonlyRecord } from "effect/Predicate"
|
|
835
1065
|
*
|
|
836
|
-
* assert.
|
|
837
|
-
* assert.
|
|
1066
|
+
* assert.strictEqual(isReadonlyRecord({}), true)
|
|
1067
|
+
* assert.strictEqual(isReadonlyRecord({ a: 1 }), true)
|
|
838
1068
|
*
|
|
839
|
-
* assert.
|
|
840
|
-
* assert.
|
|
841
|
-
* assert.deepStrictEqual(isReadonlyRecord(null), false)
|
|
842
|
-
* assert.deepStrictEqual(isReadonlyRecord(undefined), false)
|
|
1069
|
+
* assert.strictEqual(isReadonlyRecord([]), false)
|
|
1070
|
+
* assert.strictEqual(isReadonlyRecord(null), false)
|
|
843
1071
|
* ```
|
|
844
1072
|
*
|
|
845
1073
|
* @category guards
|
|
@@ -850,19 +1078,24 @@ export const isReadonlyRecord: (
|
|
|
850
1078
|
) => input is { readonly [x: string | symbol]: unknown } = isRecord
|
|
851
1079
|
|
|
852
1080
|
/**
|
|
853
|
-
* A
|
|
1081
|
+
* A refinement that checks if a value is a `Promise`. It performs a duck-typing check
|
|
1082
|
+
* for `.then` and `.catch` methods.
|
|
854
1083
|
*
|
|
855
1084
|
* @example
|
|
856
1085
|
* ```ts
|
|
857
1086
|
* import * as assert from "node:assert"
|
|
858
1087
|
* import { isPromise } from "effect/Predicate"
|
|
859
1088
|
*
|
|
860
|
-
* assert.
|
|
861
|
-
* assert.
|
|
1089
|
+
* assert.strictEqual(isPromise(Promise.resolve(1)), true)
|
|
1090
|
+
* assert.strictEqual(isPromise(new Promise(() => {})), true)
|
|
1091
|
+
*
|
|
1092
|
+
* assert.strictEqual(isPromise({ then() {} }), false) // Missing .catch
|
|
1093
|
+
* assert.strictEqual(isPromise({}), false)
|
|
862
1094
|
* ```
|
|
863
1095
|
*
|
|
864
1096
|
* @category guards
|
|
865
1097
|
* @since 2.0.0
|
|
1098
|
+
* @see isPromiseLike
|
|
866
1099
|
*/
|
|
867
1100
|
export const isPromise = (
|
|
868
1101
|
input: unknown
|
|
@@ -870,23 +1103,40 @@ export const isPromise = (
|
|
|
870
1103
|
hasProperty(input, "then") && "catch" in input && isFunction(input.then) && isFunction(input.catch)
|
|
871
1104
|
|
|
872
1105
|
/**
|
|
1106
|
+
* A refinement that checks if a value is `PromiseLike`. It performs a duck-typing
|
|
1107
|
+
* check for a `.then` method.
|
|
1108
|
+
*
|
|
1109
|
+
* @example
|
|
1110
|
+
* ```ts
|
|
1111
|
+
* import * as assert from "node:assert"
|
|
1112
|
+
* import { isPromiseLike } from "effect/Predicate"
|
|
1113
|
+
*
|
|
1114
|
+
* assert.strictEqual(isPromiseLike(Promise.resolve(1)), true)
|
|
1115
|
+
* assert.strictEqual(isPromiseLike({ then: () => {} }), true)
|
|
1116
|
+
*
|
|
1117
|
+
* assert.strictEqual(isPromiseLike({}), false)
|
|
1118
|
+
* ```
|
|
1119
|
+
*
|
|
873
1120
|
* @category guards
|
|
874
1121
|
* @since 2.0.0
|
|
1122
|
+
* @see isPromise
|
|
875
1123
|
*/
|
|
876
1124
|
export const isPromiseLike = (
|
|
877
1125
|
input: unknown
|
|
878
1126
|
): input is PromiseLike<unknown> => hasProperty(input, "then") && isFunction(input.then)
|
|
879
1127
|
|
|
880
1128
|
/**
|
|
881
|
-
*
|
|
1129
|
+
* A refinement that checks if a value is a `RegExp`.
|
|
882
1130
|
*
|
|
883
1131
|
* @example
|
|
884
1132
|
* ```ts
|
|
885
1133
|
* import * as assert from "node:assert"
|
|
886
1134
|
* import { Predicate } from "effect"
|
|
887
1135
|
*
|
|
888
|
-
* assert.
|
|
889
|
-
* assert.
|
|
1136
|
+
* assert.strictEqual(Predicate.isRegExp(/a/), true)
|
|
1137
|
+
* assert.strictEqual(Predicate.isRegExp(new RegExp("a")), true)
|
|
1138
|
+
*
|
|
1139
|
+
* assert.strictEqual(Predicate.isRegExp("/a/"), false)
|
|
890
1140
|
* ```
|
|
891
1141
|
*
|
|
892
1142
|
* @category guards
|
|
@@ -895,22 +1145,157 @@ export const isPromiseLike = (
|
|
|
895
1145
|
export const isRegExp = (input: unknown): input is RegExp => input instanceof RegExp
|
|
896
1146
|
|
|
897
1147
|
/**
|
|
1148
|
+
* Composes a `Refinement` with another `Refinement` or `Predicate`.
|
|
1149
|
+
*
|
|
1150
|
+
* This can be used to chain checks. The first refinement is applied, and if it
|
|
1151
|
+
* passes, the second check is applied to the same value, potentially refining
|
|
1152
|
+
* the type further.
|
|
1153
|
+
*
|
|
1154
|
+
* @example
|
|
1155
|
+
* ```ts
|
|
1156
|
+
* import { Predicate } from "effect"
|
|
1157
|
+
* import * as assert from "node:assert"
|
|
1158
|
+
*
|
|
1159
|
+
* const isString = (u: unknown): u is string => typeof u === "string"
|
|
1160
|
+
* const minLength = (n: number) => (s: string): boolean => s.length >= n
|
|
1161
|
+
*
|
|
1162
|
+
* // Create a refinement that checks for a string with a minimum length of 3
|
|
1163
|
+
* const isLongString = Predicate.compose(isString, minLength(3))
|
|
1164
|
+
*
|
|
1165
|
+
* let value: unknown = "hello"
|
|
1166
|
+
*
|
|
1167
|
+
* assert.strictEqual(isLongString(value), true)
|
|
1168
|
+
* if (isLongString(value)) {
|
|
1169
|
+
* // value is narrowed to string
|
|
1170
|
+
* assert.strictEqual(value.toUpperCase(), "HELLO")
|
|
1171
|
+
* }
|
|
1172
|
+
* assert.strictEqual(isLongString("hi"), false)
|
|
1173
|
+
* ```
|
|
1174
|
+
*
|
|
898
1175
|
* @since 2.0.0
|
|
899
1176
|
*/
|
|
900
1177
|
export const compose: {
|
|
901
1178
|
/**
|
|
1179
|
+
* Composes a `Refinement` with another `Refinement` or `Predicate`.
|
|
1180
|
+
*
|
|
1181
|
+
* This can be used to chain checks. The first refinement is applied, and if it
|
|
1182
|
+
* passes, the second check is applied to the same value, potentially refining
|
|
1183
|
+
* the type further.
|
|
1184
|
+
*
|
|
1185
|
+
* @example
|
|
1186
|
+
* ```ts
|
|
1187
|
+
* import { Predicate } from "effect"
|
|
1188
|
+
* import * as assert from "node:assert"
|
|
1189
|
+
*
|
|
1190
|
+
* const isString = (u: unknown): u is string => typeof u === "string"
|
|
1191
|
+
* const minLength = (n: number) => (s: string): boolean => s.length >= n
|
|
1192
|
+
*
|
|
1193
|
+
* // Create a refinement that checks for a string with a minimum length of 3
|
|
1194
|
+
* const isLongString = Predicate.compose(isString, minLength(3))
|
|
1195
|
+
*
|
|
1196
|
+
* let value: unknown = "hello"
|
|
1197
|
+
*
|
|
1198
|
+
* assert.strictEqual(isLongString(value), true)
|
|
1199
|
+
* if (isLongString(value)) {
|
|
1200
|
+
* // value is narrowed to string
|
|
1201
|
+
* assert.strictEqual(value.toUpperCase(), "HELLO")
|
|
1202
|
+
* }
|
|
1203
|
+
* assert.strictEqual(isLongString("hi"), false)
|
|
1204
|
+
* ```
|
|
1205
|
+
*
|
|
902
1206
|
* @since 2.0.0
|
|
903
1207
|
*/
|
|
904
1208
|
<A, B extends A, C extends B, D extends C>(bc: Refinement<C, D>): (ab: Refinement<A, B>) => Refinement<A, D>
|
|
905
1209
|
/**
|
|
1210
|
+
* Composes a `Refinement` with another `Refinement` or `Predicate`.
|
|
1211
|
+
*
|
|
1212
|
+
* This can be used to chain checks. The first refinement is applied, and if it
|
|
1213
|
+
* passes, the second check is applied to the same value, potentially refining
|
|
1214
|
+
* the type further.
|
|
1215
|
+
*
|
|
1216
|
+
* @example
|
|
1217
|
+
* ```ts
|
|
1218
|
+
* import { Predicate } from "effect"
|
|
1219
|
+
* import * as assert from "node:assert"
|
|
1220
|
+
*
|
|
1221
|
+
* const isString = (u: unknown): u is string => typeof u === "string"
|
|
1222
|
+
* const minLength = (n: number) => (s: string): boolean => s.length >= n
|
|
1223
|
+
*
|
|
1224
|
+
* // Create a refinement that checks for a string with a minimum length of 3
|
|
1225
|
+
* const isLongString = Predicate.compose(isString, minLength(3))
|
|
1226
|
+
*
|
|
1227
|
+
* let value: unknown = "hello"
|
|
1228
|
+
*
|
|
1229
|
+
* assert.strictEqual(isLongString(value), true)
|
|
1230
|
+
* if (isLongString(value)) {
|
|
1231
|
+
* // value is narrowed to string
|
|
1232
|
+
* assert.strictEqual(value.toUpperCase(), "HELLO")
|
|
1233
|
+
* }
|
|
1234
|
+
* assert.strictEqual(isLongString("hi"), false)
|
|
1235
|
+
* ```
|
|
1236
|
+
*
|
|
906
1237
|
* @since 2.0.0
|
|
907
1238
|
*/
|
|
908
1239
|
<A, B extends A>(bc: Predicate<NoInfer<B>>): (ab: Refinement<A, B>) => Refinement<A, B>
|
|
909
1240
|
/**
|
|
1241
|
+
* Composes a `Refinement` with another `Refinement` or `Predicate`.
|
|
1242
|
+
*
|
|
1243
|
+
* This can be used to chain checks. The first refinement is applied, and if it
|
|
1244
|
+
* passes, the second check is applied to the same value, potentially refining
|
|
1245
|
+
* the type further.
|
|
1246
|
+
*
|
|
1247
|
+
* @example
|
|
1248
|
+
* ```ts
|
|
1249
|
+
* import { Predicate } from "effect"
|
|
1250
|
+
* import * as assert from "node:assert"
|
|
1251
|
+
*
|
|
1252
|
+
* const isString = (u: unknown): u is string => typeof u === "string"
|
|
1253
|
+
* const minLength = (n: number) => (s: string): boolean => s.length >= n
|
|
1254
|
+
*
|
|
1255
|
+
* // Create a refinement that checks for a string with a minimum length of 3
|
|
1256
|
+
* const isLongString = Predicate.compose(isString, minLength(3))
|
|
1257
|
+
*
|
|
1258
|
+
* let value: unknown = "hello"
|
|
1259
|
+
*
|
|
1260
|
+
* assert.strictEqual(isLongString(value), true)
|
|
1261
|
+
* if (isLongString(value)) {
|
|
1262
|
+
* // value is narrowed to string
|
|
1263
|
+
* assert.strictEqual(value.toUpperCase(), "HELLO")
|
|
1264
|
+
* }
|
|
1265
|
+
* assert.strictEqual(isLongString("hi"), false)
|
|
1266
|
+
* ```
|
|
1267
|
+
*
|
|
910
1268
|
* @since 2.0.0
|
|
911
1269
|
*/
|
|
912
1270
|
<A, B extends A, C extends B, D extends C>(ab: Refinement<A, B>, bc: Refinement<C, D>): Refinement<A, D>
|
|
913
1271
|
/**
|
|
1272
|
+
* Composes a `Refinement` with another `Refinement` or `Predicate`.
|
|
1273
|
+
*
|
|
1274
|
+
* This can be used to chain checks. The first refinement is applied, and if it
|
|
1275
|
+
* passes, the second check is applied to the same value, potentially refining
|
|
1276
|
+
* the type further.
|
|
1277
|
+
*
|
|
1278
|
+
* @example
|
|
1279
|
+
* ```ts
|
|
1280
|
+
* import { Predicate } from "effect"
|
|
1281
|
+
* import * as assert from "node:assert"
|
|
1282
|
+
*
|
|
1283
|
+
* const isString = (u: unknown): u is string => typeof u === "string"
|
|
1284
|
+
* const minLength = (n: number) => (s: string): boolean => s.length >= n
|
|
1285
|
+
*
|
|
1286
|
+
* // Create a refinement that checks for a string with a minimum length of 3
|
|
1287
|
+
* const isLongString = Predicate.compose(isString, minLength(3))
|
|
1288
|
+
*
|
|
1289
|
+
* let value: unknown = "hello"
|
|
1290
|
+
*
|
|
1291
|
+
* assert.strictEqual(isLongString(value), true)
|
|
1292
|
+
* if (isLongString(value)) {
|
|
1293
|
+
* // value is narrowed to string
|
|
1294
|
+
* assert.strictEqual(value.toUpperCase(), "HELLO")
|
|
1295
|
+
* }
|
|
1296
|
+
* assert.strictEqual(isLongString("hi"), false)
|
|
1297
|
+
* ```
|
|
1298
|
+
*
|
|
914
1299
|
* @since 2.0.0
|
|
915
1300
|
*/
|
|
916
1301
|
<A, B extends A>(ab: Refinement<A, B>, bc: Predicate<NoInfer<B>>): Refinement<A, B>
|
|
@@ -921,6 +1306,9 @@ export const compose: {
|
|
|
921
1306
|
)
|
|
922
1307
|
|
|
923
1308
|
/**
|
|
1309
|
+
* Combines two predicates to test a tuple of two values. The first predicate tests the
|
|
1310
|
+
* first element of the tuple, and the second predicate tests the second element.
|
|
1311
|
+
*
|
|
924
1312
|
* @category combining
|
|
925
1313
|
* @since 2.0.0
|
|
926
1314
|
*/
|
|
@@ -929,8 +1317,14 @@ export const product =
|
|
|
929
1317
|
([a, b]) => self(a) && that(b)
|
|
930
1318
|
|
|
931
1319
|
/**
|
|
1320
|
+
* Takes an iterable of predicates and returns a new predicate that tests an array of values.
|
|
1321
|
+
* The new predicate returns `true` if each predicate at a given index is satisfied by the
|
|
1322
|
+
* value at the same index in the array. The check stops at the length of the shorter of
|
|
1323
|
+
* the two iterables (predicates or values).
|
|
1324
|
+
*
|
|
932
1325
|
* @category combining
|
|
933
1326
|
* @since 2.0.0
|
|
1327
|
+
* @see tuple for a more powerful, variadic version.
|
|
934
1328
|
*/
|
|
935
1329
|
export const all = <A>(
|
|
936
1330
|
collection: Iterable<Predicate<A>>
|
|
@@ -951,6 +1345,9 @@ export const all = <A>(
|
|
|
951
1345
|
}
|
|
952
1346
|
|
|
953
1347
|
/**
|
|
1348
|
+
* Combines a predicate for a single value and an iterable of predicates for the rest of an array.
|
|
1349
|
+
* Useful for checking the head and tail of an array separately.
|
|
1350
|
+
*
|
|
954
1351
|
* @category combining
|
|
955
1352
|
* @since 2.0.0
|
|
956
1353
|
*/
|
|
@@ -963,24 +1360,66 @@ export const productMany = <A>(
|
|
|
963
1360
|
}
|
|
964
1361
|
|
|
965
1362
|
/**
|
|
966
|
-
*
|
|
1363
|
+
* Combines an array of predicates into a single predicate that tests an array of values.
|
|
1364
|
+
* This function is highly type-aware and will produce a `Refinement` if any of the provided
|
|
1365
|
+
* predicates are `Refinement`s, allowing for powerful type-narrowing of tuples.
|
|
967
1366
|
*
|
|
968
|
-
*
|
|
969
|
-
*
|
|
970
|
-
*
|
|
971
|
-
*
|
|
1367
|
+
* - If all predicates are `Predicate<T>`, the result is `Predicate<[T, T, ...]>`.
|
|
1368
|
+
* - If any predicate is a `Refinement<A, B>`, the result is a `Refinement` that narrows
|
|
1369
|
+
* the input tuple type to a more specific tuple type.
|
|
1370
|
+
*
|
|
1371
|
+
* @example
|
|
1372
|
+
* ```ts
|
|
1373
|
+
* import * as assert from "node:assert"
|
|
1374
|
+
* import { Predicate } from "effect"
|
|
1375
|
+
*
|
|
1376
|
+
* const isString = (u: unknown): u is string => typeof u === "string"
|
|
1377
|
+
* const isNumber = (u: unknown): u is number => typeof u === "number"
|
|
1378
|
+
*
|
|
1379
|
+
* // Create a refinement for a [string, number] tuple
|
|
1380
|
+
* const isStringNumberTuple = Predicate.tuple(isString, isNumber)
|
|
1381
|
+
*
|
|
1382
|
+
* const value: [unknown, unknown] = ["hello", 123]
|
|
1383
|
+
* if (isStringNumberTuple(value)) {
|
|
1384
|
+
* // value is narrowed to [string, number]
|
|
1385
|
+
* const [s, n] = value
|
|
1386
|
+
* assert.strictEqual(s.toUpperCase(), "HELLO")
|
|
1387
|
+
* assert.strictEqual(n.toFixed(2), "123.00")
|
|
1388
|
+
* }
|
|
1389
|
+
* assert.strictEqual(isStringNumberTuple(["hello", "123"]), false)
|
|
972
1390
|
* ```
|
|
973
1391
|
*
|
|
974
1392
|
* @since 2.0.0
|
|
975
1393
|
*/
|
|
976
1394
|
export const tuple: {
|
|
977
1395
|
/**
|
|
978
|
-
*
|
|
1396
|
+
* Combines an array of predicates into a single predicate that tests an array of values.
|
|
1397
|
+
* This function is highly type-aware and will produce a `Refinement` if any of the provided
|
|
1398
|
+
* predicates are `Refinement`s, allowing for powerful type-narrowing of tuples.
|
|
1399
|
+
*
|
|
1400
|
+
* - If all predicates are `Predicate<T>`, the result is `Predicate<[T, T, ...]>`.
|
|
1401
|
+
* - If any predicate is a `Refinement<A, B>`, the result is a `Refinement` that narrows
|
|
1402
|
+
* the input tuple type to a more specific tuple type.
|
|
979
1403
|
*
|
|
980
|
-
*
|
|
981
|
-
*
|
|
982
|
-
*
|
|
983
|
-
*
|
|
1404
|
+
* @example
|
|
1405
|
+
* ```ts
|
|
1406
|
+
* import * as assert from "node:assert"
|
|
1407
|
+
* import { Predicate } from "effect"
|
|
1408
|
+
*
|
|
1409
|
+
* const isString = (u: unknown): u is string => typeof u === "string"
|
|
1410
|
+
* const isNumber = (u: unknown): u is number => typeof u === "number"
|
|
1411
|
+
*
|
|
1412
|
+
* // Create a refinement for a [string, number] tuple
|
|
1413
|
+
* const isStringNumberTuple = Predicate.tuple(isString, isNumber)
|
|
1414
|
+
*
|
|
1415
|
+
* const value: [unknown, unknown] = ["hello", 123]
|
|
1416
|
+
* if (isStringNumberTuple(value)) {
|
|
1417
|
+
* // value is narrowed to [string, number]
|
|
1418
|
+
* const [s, n] = value
|
|
1419
|
+
* assert.strictEqual(s.toUpperCase(), "HELLO")
|
|
1420
|
+
* assert.strictEqual(n.toFixed(2), "123.00")
|
|
1421
|
+
* }
|
|
1422
|
+
* assert.strictEqual(isStringNumberTuple(["hello", "123"]), false)
|
|
984
1423
|
* ```
|
|
985
1424
|
*
|
|
986
1425
|
* @since 2.0.0
|
|
@@ -993,20 +1432,68 @@ export const tuple: {
|
|
|
993
1432
|
} = (...elements: ReadonlyArray<Predicate.Any>) => all(elements) as any
|
|
994
1433
|
|
|
995
1434
|
/**
|
|
996
|
-
*
|
|
997
|
-
*
|
|
998
|
-
*
|
|
999
|
-
*
|
|
1435
|
+
* Combines a record of predicates into a single predicate that tests a record of values.
|
|
1436
|
+
* This function is highly type-aware and will produce a `Refinement` if any of the provided
|
|
1437
|
+
* predicates are `Refinement`s, allowing for powerful type-narrowing of structs.
|
|
1438
|
+
*
|
|
1439
|
+
* - If all predicates are `Predicate<T>`, the result is `Predicate<{ k: T, ... }>`.
|
|
1440
|
+
* - If any predicate is a `Refinement<A, B>`, the result is a `Refinement` that narrows
|
|
1441
|
+
* the input record type to a more specific record type.
|
|
1442
|
+
*
|
|
1443
|
+
* @example
|
|
1444
|
+
* ```ts
|
|
1445
|
+
* import * as assert from "node:assert"
|
|
1446
|
+
* import { Predicate } from "effect"
|
|
1447
|
+
*
|
|
1448
|
+
* const isString = (u: unknown): u is string => typeof u === "string"
|
|
1449
|
+
* const isNumber = (u: unknown): u is number => typeof u === "number"
|
|
1450
|
+
*
|
|
1451
|
+
* const personPredicate = Predicate.struct({
|
|
1452
|
+
* name: isString,
|
|
1453
|
+
* age: isNumber
|
|
1454
|
+
* })
|
|
1455
|
+
*
|
|
1456
|
+
* const value: { name: unknown; age: unknown } = { name: "Alice", age: 30 }
|
|
1457
|
+
* if (personPredicate(value)) {
|
|
1458
|
+
* // value is narrowed to { name: string; age: number }
|
|
1459
|
+
* assert.strictEqual(value.name.toUpperCase(), "ALICE")
|
|
1460
|
+
* assert.strictEqual(value.age.toFixed(0), "30")
|
|
1461
|
+
* }
|
|
1462
|
+
* assert.strictEqual(personPredicate({ name: "Bob", age: "40" }), false)
|
|
1000
1463
|
* ```
|
|
1001
1464
|
*
|
|
1002
1465
|
* @since 2.0.0
|
|
1003
1466
|
*/
|
|
1004
1467
|
export const struct: {
|
|
1005
1468
|
/**
|
|
1006
|
-
*
|
|
1007
|
-
*
|
|
1008
|
-
*
|
|
1009
|
-
*
|
|
1469
|
+
* Combines a record of predicates into a single predicate that tests a record of values.
|
|
1470
|
+
* This function is highly type-aware and will produce a `Refinement` if any of the provided
|
|
1471
|
+
* predicates are `Refinement`s, allowing for powerful type-narrowing of structs.
|
|
1472
|
+
*
|
|
1473
|
+
* - If all predicates are `Predicate<T>`, the result is `Predicate<{ k: T, ... }>`.
|
|
1474
|
+
* - If any predicate is a `Refinement<A, B>`, the result is a `Refinement` that narrows
|
|
1475
|
+
* the input record type to a more specific record type.
|
|
1476
|
+
*
|
|
1477
|
+
* @example
|
|
1478
|
+
* ```ts
|
|
1479
|
+
* import * as assert from "node:assert"
|
|
1480
|
+
* import { Predicate } from "effect"
|
|
1481
|
+
*
|
|
1482
|
+
* const isString = (u: unknown): u is string => typeof u === "string"
|
|
1483
|
+
* const isNumber = (u: unknown): u is number => typeof u === "number"
|
|
1484
|
+
*
|
|
1485
|
+
* const personPredicate = Predicate.struct({
|
|
1486
|
+
* name: isString,
|
|
1487
|
+
* age: isNumber
|
|
1488
|
+
* })
|
|
1489
|
+
*
|
|
1490
|
+
* const value: { name: unknown; age: unknown } = { name: "Alice", age: 30 }
|
|
1491
|
+
* if (personPredicate(value)) {
|
|
1492
|
+
* // value is narrowed to { name: string; age: number }
|
|
1493
|
+
* assert.strictEqual(value.name.toUpperCase(), "ALICE")
|
|
1494
|
+
* assert.strictEqual(value.age.toFixed(0), "30")
|
|
1495
|
+
* }
|
|
1496
|
+
* assert.strictEqual(personPredicate({ name: "Bob", age: "40" }), false)
|
|
1010
1497
|
* ```
|
|
1011
1498
|
*
|
|
1012
1499
|
* @since 2.0.0
|
|
@@ -1030,18 +1517,21 @@ export const struct: {
|
|
|
1030
1517
|
}) as any
|
|
1031
1518
|
|
|
1032
1519
|
/**
|
|
1033
|
-
*
|
|
1520
|
+
* Returns a new predicate that is the logical negation of the given predicate.
|
|
1521
|
+
*
|
|
1522
|
+
* **Note**: If the input is a `Refinement`, the resulting predicate will be a
|
|
1523
|
+
* simple `Predicate`, as TypeScript cannot infer the negative type.
|
|
1034
1524
|
*
|
|
1035
1525
|
* @example
|
|
1036
1526
|
* ```ts
|
|
1037
1527
|
* import * as assert from "node:assert"
|
|
1038
1528
|
* import { Predicate, Number } from "effect"
|
|
1039
1529
|
*
|
|
1040
|
-
* const
|
|
1530
|
+
* const isNonPositive = Predicate.not(Number.greaterThan(0))
|
|
1041
1531
|
*
|
|
1042
|
-
* assert.
|
|
1043
|
-
* assert.
|
|
1044
|
-
* assert.
|
|
1532
|
+
* assert.strictEqual(isNonPositive(-1), true)
|
|
1533
|
+
* assert.strictEqual(isNonPositive(0), true)
|
|
1534
|
+
* assert.strictEqual(isNonPositive(1), false)
|
|
1045
1535
|
* ```
|
|
1046
1536
|
*
|
|
1047
1537
|
* @category combinators
|
|
@@ -1050,18 +1540,31 @@ export const struct: {
|
|
|
1050
1540
|
export const not = <A>(self: Predicate<A>): Predicate<A> => (a) => !self(a)
|
|
1051
1541
|
|
|
1052
1542
|
/**
|
|
1053
|
-
* Combines two predicates
|
|
1543
|
+
* Combines two predicates with a logical "OR". The resulting predicate returns `true`
|
|
1544
|
+
* if at least one of the predicates returns `true`.
|
|
1545
|
+
*
|
|
1546
|
+
* If both predicates are `Refinement`s, the resulting predicate is a `Refinement` to the
|
|
1547
|
+
* union of their target types (`B | C`).
|
|
1054
1548
|
*
|
|
1055
1549
|
* @example
|
|
1056
1550
|
* ```ts
|
|
1057
1551
|
* import * as assert from "node:assert"
|
|
1058
|
-
* import { Predicate
|
|
1552
|
+
* import { Predicate } from "effect"
|
|
1553
|
+
*
|
|
1554
|
+
* const isString = (u: unknown): u is string => typeof u === "string"
|
|
1555
|
+
* const isNumber = (u: unknown): u is number => typeof u === "number"
|
|
1556
|
+
*
|
|
1557
|
+
* const isStringOrNumber = Predicate.or(isString, isNumber)
|
|
1059
1558
|
*
|
|
1060
|
-
*
|
|
1559
|
+
* assert.strictEqual(isStringOrNumber("hello"), true)
|
|
1560
|
+
* assert.strictEqual(isStringOrNumber(123), true)
|
|
1561
|
+
* assert.strictEqual(isStringOrNumber(null), false)
|
|
1061
1562
|
*
|
|
1062
|
-
*
|
|
1063
|
-
*
|
|
1064
|
-
*
|
|
1563
|
+
* const value: unknown = "world"
|
|
1564
|
+
* if (isStringOrNumber(value)) {
|
|
1565
|
+
* // value is narrowed to string | number
|
|
1566
|
+
* console.log(value)
|
|
1567
|
+
* }
|
|
1065
1568
|
* ```
|
|
1066
1569
|
*
|
|
1067
1570
|
* @category combinators
|
|
@@ -1069,18 +1572,31 @@ export const not = <A>(self: Predicate<A>): Predicate<A> => (a) => !self(a)
|
|
|
1069
1572
|
*/
|
|
1070
1573
|
export const or: {
|
|
1071
1574
|
/**
|
|
1072
|
-
* Combines two predicates
|
|
1575
|
+
* Combines two predicates with a logical "OR". The resulting predicate returns `true`
|
|
1576
|
+
* if at least one of the predicates returns `true`.
|
|
1577
|
+
*
|
|
1578
|
+
* If both predicates are `Refinement`s, the resulting predicate is a `Refinement` to the
|
|
1579
|
+
* union of their target types (`B | C`).
|
|
1073
1580
|
*
|
|
1074
1581
|
* @example
|
|
1075
1582
|
* ```ts
|
|
1076
1583
|
* import * as assert from "node:assert"
|
|
1077
|
-
* import { Predicate
|
|
1584
|
+
* import { Predicate } from "effect"
|
|
1585
|
+
*
|
|
1586
|
+
* const isString = (u: unknown): u is string => typeof u === "string"
|
|
1587
|
+
* const isNumber = (u: unknown): u is number => typeof u === "number"
|
|
1588
|
+
*
|
|
1589
|
+
* const isStringOrNumber = Predicate.or(isString, isNumber)
|
|
1078
1590
|
*
|
|
1079
|
-
*
|
|
1591
|
+
* assert.strictEqual(isStringOrNumber("hello"), true)
|
|
1592
|
+
* assert.strictEqual(isStringOrNumber(123), true)
|
|
1593
|
+
* assert.strictEqual(isStringOrNumber(null), false)
|
|
1080
1594
|
*
|
|
1081
|
-
*
|
|
1082
|
-
*
|
|
1083
|
-
*
|
|
1595
|
+
* const value: unknown = "world"
|
|
1596
|
+
* if (isStringOrNumber(value)) {
|
|
1597
|
+
* // value is narrowed to string | number
|
|
1598
|
+
* console.log(value)
|
|
1599
|
+
* }
|
|
1084
1600
|
* ```
|
|
1085
1601
|
*
|
|
1086
1602
|
* @category combinators
|
|
@@ -1088,18 +1604,31 @@ export const or: {
|
|
|
1088
1604
|
*/
|
|
1089
1605
|
<A, C extends A>(that: Refinement<A, C>): <B extends A>(self: Refinement<A, B>) => Refinement<A, B | C>
|
|
1090
1606
|
/**
|
|
1091
|
-
* Combines two predicates
|
|
1607
|
+
* Combines two predicates with a logical "OR". The resulting predicate returns `true`
|
|
1608
|
+
* if at least one of the predicates returns `true`.
|
|
1609
|
+
*
|
|
1610
|
+
* If both predicates are `Refinement`s, the resulting predicate is a `Refinement` to the
|
|
1611
|
+
* union of their target types (`B | C`).
|
|
1092
1612
|
*
|
|
1093
1613
|
* @example
|
|
1094
1614
|
* ```ts
|
|
1095
1615
|
* import * as assert from "node:assert"
|
|
1096
|
-
* import { Predicate
|
|
1616
|
+
* import { Predicate } from "effect"
|
|
1097
1617
|
*
|
|
1098
|
-
* const
|
|
1618
|
+
* const isString = (u: unknown): u is string => typeof u === "string"
|
|
1619
|
+
* const isNumber = (u: unknown): u is number => typeof u === "number"
|
|
1099
1620
|
*
|
|
1100
|
-
*
|
|
1101
|
-
*
|
|
1102
|
-
* assert.
|
|
1621
|
+
* const isStringOrNumber = Predicate.or(isString, isNumber)
|
|
1622
|
+
*
|
|
1623
|
+
* assert.strictEqual(isStringOrNumber("hello"), true)
|
|
1624
|
+
* assert.strictEqual(isStringOrNumber(123), true)
|
|
1625
|
+
* assert.strictEqual(isStringOrNumber(null), false)
|
|
1626
|
+
*
|
|
1627
|
+
* const value: unknown = "world"
|
|
1628
|
+
* if (isStringOrNumber(value)) {
|
|
1629
|
+
* // value is narrowed to string | number
|
|
1630
|
+
* console.log(value)
|
|
1631
|
+
* }
|
|
1103
1632
|
* ```
|
|
1104
1633
|
*
|
|
1105
1634
|
* @category combinators
|
|
@@ -1107,18 +1636,31 @@ export const or: {
|
|
|
1107
1636
|
*/
|
|
1108
1637
|
<A, B extends A, C extends A>(self: Refinement<A, B>, that: Refinement<A, C>): Refinement<A, B | C>
|
|
1109
1638
|
/**
|
|
1110
|
-
* Combines two predicates
|
|
1639
|
+
* Combines two predicates with a logical "OR". The resulting predicate returns `true`
|
|
1640
|
+
* if at least one of the predicates returns `true`.
|
|
1641
|
+
*
|
|
1642
|
+
* If both predicates are `Refinement`s, the resulting predicate is a `Refinement` to the
|
|
1643
|
+
* union of their target types (`B | C`).
|
|
1111
1644
|
*
|
|
1112
1645
|
* @example
|
|
1113
1646
|
* ```ts
|
|
1114
1647
|
* import * as assert from "node:assert"
|
|
1115
|
-
* import { Predicate
|
|
1648
|
+
* import { Predicate } from "effect"
|
|
1116
1649
|
*
|
|
1117
|
-
* const
|
|
1650
|
+
* const isString = (u: unknown): u is string => typeof u === "string"
|
|
1651
|
+
* const isNumber = (u: unknown): u is number => typeof u === "number"
|
|
1118
1652
|
*
|
|
1119
|
-
*
|
|
1120
|
-
*
|
|
1121
|
-
* assert.
|
|
1653
|
+
* const isStringOrNumber = Predicate.or(isString, isNumber)
|
|
1654
|
+
*
|
|
1655
|
+
* assert.strictEqual(isStringOrNumber("hello"), true)
|
|
1656
|
+
* assert.strictEqual(isStringOrNumber(123), true)
|
|
1657
|
+
* assert.strictEqual(isStringOrNumber(null), false)
|
|
1658
|
+
*
|
|
1659
|
+
* const value: unknown = "world"
|
|
1660
|
+
* if (isStringOrNumber(value)) {
|
|
1661
|
+
* // value is narrowed to string | number
|
|
1662
|
+
* console.log(value)
|
|
1663
|
+
* }
|
|
1122
1664
|
* ```
|
|
1123
1665
|
*
|
|
1124
1666
|
* @category combinators
|
|
@@ -1126,18 +1668,31 @@ export const or: {
|
|
|
1126
1668
|
*/
|
|
1127
1669
|
<A>(that: Predicate<A>): (self: Predicate<A>) => Predicate<A>
|
|
1128
1670
|
/**
|
|
1129
|
-
* Combines two predicates
|
|
1671
|
+
* Combines two predicates with a logical "OR". The resulting predicate returns `true`
|
|
1672
|
+
* if at least one of the predicates returns `true`.
|
|
1673
|
+
*
|
|
1674
|
+
* If both predicates are `Refinement`s, the resulting predicate is a `Refinement` to the
|
|
1675
|
+
* union of their target types (`B | C`).
|
|
1130
1676
|
*
|
|
1131
1677
|
* @example
|
|
1132
1678
|
* ```ts
|
|
1133
1679
|
* import * as assert from "node:assert"
|
|
1134
|
-
* import { Predicate
|
|
1680
|
+
* import { Predicate } from "effect"
|
|
1135
1681
|
*
|
|
1136
|
-
* const
|
|
1682
|
+
* const isString = (u: unknown): u is string => typeof u === "string"
|
|
1683
|
+
* const isNumber = (u: unknown): u is number => typeof u === "number"
|
|
1137
1684
|
*
|
|
1138
|
-
*
|
|
1139
|
-
*
|
|
1140
|
-
* assert.
|
|
1685
|
+
* const isStringOrNumber = Predicate.or(isString, isNumber)
|
|
1686
|
+
*
|
|
1687
|
+
* assert.strictEqual(isStringOrNumber("hello"), true)
|
|
1688
|
+
* assert.strictEqual(isStringOrNumber(123), true)
|
|
1689
|
+
* assert.strictEqual(isStringOrNumber(null), false)
|
|
1690
|
+
*
|
|
1691
|
+
* const value: unknown = "world"
|
|
1692
|
+
* if (isStringOrNumber(value)) {
|
|
1693
|
+
* // value is narrowed to string | number
|
|
1694
|
+
* console.log(value)
|
|
1695
|
+
* }
|
|
1141
1696
|
* ```
|
|
1142
1697
|
*
|
|
1143
1698
|
* @category combinators
|
|
@@ -1147,21 +1702,34 @@ export const or: {
|
|
|
1147
1702
|
} = dual(2, <A>(self: Predicate<A>, that: Predicate<A>): Predicate<A> => (a) => self(a) || that(a))
|
|
1148
1703
|
|
|
1149
1704
|
/**
|
|
1150
|
-
* Combines two predicates
|
|
1705
|
+
* Combines two predicates with a logical "AND". The resulting predicate returns `true`
|
|
1706
|
+
* only if both of the predicates return `true`.
|
|
1707
|
+
*
|
|
1708
|
+
* If both predicates are `Refinement`s, the resulting predicate is a `Refinement` to the
|
|
1709
|
+
* intersection of their target types (`B & C`).
|
|
1151
1710
|
*
|
|
1152
1711
|
* @example
|
|
1153
1712
|
* ```ts
|
|
1154
1713
|
* import * as assert from "node:assert"
|
|
1155
1714
|
* import { Predicate } from "effect"
|
|
1156
1715
|
*
|
|
1157
|
-
*
|
|
1158
|
-
*
|
|
1716
|
+
* type Person = { name: string }
|
|
1717
|
+
* type Employee = { id: number }
|
|
1718
|
+
*
|
|
1719
|
+
* const hasName = (u: unknown): u is Person => Predicate.hasProperty(u, "name") && typeof (u as any).name === "string"
|
|
1720
|
+
* const hasId = (u: unknown): u is Employee => Predicate.hasProperty(u, "id") && typeof (u as any).id === "number"
|
|
1721
|
+
*
|
|
1722
|
+
* const isPersonAndEmployee = Predicate.and(hasName, hasId)
|
|
1159
1723
|
*
|
|
1160
|
-
* const
|
|
1724
|
+
* const val: unknown = { name: "Alice", id: 123 }
|
|
1725
|
+
* if (isPersonAndEmployee(val)) {
|
|
1726
|
+
* // val is narrowed to Person & Employee
|
|
1727
|
+
* assert.strictEqual(val.name, "Alice")
|
|
1728
|
+
* assert.strictEqual(val.id, 123)
|
|
1729
|
+
* }
|
|
1161
1730
|
*
|
|
1162
|
-
* assert.
|
|
1163
|
-
* assert.
|
|
1164
|
-
* assert.deepStrictEqual(length(2)("aaa"), false)
|
|
1731
|
+
* assert.strictEqual(isPersonAndEmployee({ name: "Bob" }), false) // Missing id
|
|
1732
|
+
* assert.strictEqual(isPersonAndEmployee({ id: 456 }), false) // Missing name
|
|
1165
1733
|
* ```
|
|
1166
1734
|
*
|
|
1167
1735
|
* @category combinators
|
|
@@ -1169,21 +1737,34 @@ export const or: {
|
|
|
1169
1737
|
*/
|
|
1170
1738
|
export const and: {
|
|
1171
1739
|
/**
|
|
1172
|
-
* Combines two predicates
|
|
1740
|
+
* Combines two predicates with a logical "AND". The resulting predicate returns `true`
|
|
1741
|
+
* only if both of the predicates return `true`.
|
|
1742
|
+
*
|
|
1743
|
+
* If both predicates are `Refinement`s, the resulting predicate is a `Refinement` to the
|
|
1744
|
+
* intersection of their target types (`B & C`).
|
|
1173
1745
|
*
|
|
1174
1746
|
* @example
|
|
1175
1747
|
* ```ts
|
|
1176
1748
|
* import * as assert from "node:assert"
|
|
1177
1749
|
* import { Predicate } from "effect"
|
|
1178
1750
|
*
|
|
1179
|
-
*
|
|
1180
|
-
*
|
|
1751
|
+
* type Person = { name: string }
|
|
1752
|
+
* type Employee = { id: number }
|
|
1753
|
+
*
|
|
1754
|
+
* const hasName = (u: unknown): u is Person => Predicate.hasProperty(u, "name") && typeof (u as any).name === "string"
|
|
1755
|
+
* const hasId = (u: unknown): u is Employee => Predicate.hasProperty(u, "id") && typeof (u as any).id === "number"
|
|
1181
1756
|
*
|
|
1182
|
-
* const
|
|
1757
|
+
* const isPersonAndEmployee = Predicate.and(hasName, hasId)
|
|
1183
1758
|
*
|
|
1184
|
-
*
|
|
1185
|
-
*
|
|
1186
|
-
*
|
|
1759
|
+
* const val: unknown = { name: "Alice", id: 123 }
|
|
1760
|
+
* if (isPersonAndEmployee(val)) {
|
|
1761
|
+
* // val is narrowed to Person & Employee
|
|
1762
|
+
* assert.strictEqual(val.name, "Alice")
|
|
1763
|
+
* assert.strictEqual(val.id, 123)
|
|
1764
|
+
* }
|
|
1765
|
+
*
|
|
1766
|
+
* assert.strictEqual(isPersonAndEmployee({ name: "Bob" }), false) // Missing id
|
|
1767
|
+
* assert.strictEqual(isPersonAndEmployee({ id: 456 }), false) // Missing name
|
|
1187
1768
|
* ```
|
|
1188
1769
|
*
|
|
1189
1770
|
* @category combinators
|
|
@@ -1191,21 +1772,34 @@ export const and: {
|
|
|
1191
1772
|
*/
|
|
1192
1773
|
<A, C extends A>(that: Refinement<A, C>): <B extends A>(self: Refinement<A, B>) => Refinement<A, B & C>
|
|
1193
1774
|
/**
|
|
1194
|
-
* Combines two predicates
|
|
1775
|
+
* Combines two predicates with a logical "AND". The resulting predicate returns `true`
|
|
1776
|
+
* only if both of the predicates return `true`.
|
|
1777
|
+
*
|
|
1778
|
+
* If both predicates are `Refinement`s, the resulting predicate is a `Refinement` to the
|
|
1779
|
+
* intersection of their target types (`B & C`).
|
|
1195
1780
|
*
|
|
1196
1781
|
* @example
|
|
1197
1782
|
* ```ts
|
|
1198
1783
|
* import * as assert from "node:assert"
|
|
1199
1784
|
* import { Predicate } from "effect"
|
|
1200
1785
|
*
|
|
1201
|
-
*
|
|
1202
|
-
*
|
|
1786
|
+
* type Person = { name: string }
|
|
1787
|
+
* type Employee = { id: number }
|
|
1203
1788
|
*
|
|
1204
|
-
* const
|
|
1789
|
+
* const hasName = (u: unknown): u is Person => Predicate.hasProperty(u, "name") && typeof (u as any).name === "string"
|
|
1790
|
+
* const hasId = (u: unknown): u is Employee => Predicate.hasProperty(u, "id") && typeof (u as any).id === "number"
|
|
1791
|
+
*
|
|
1792
|
+
* const isPersonAndEmployee = Predicate.and(hasName, hasId)
|
|
1793
|
+
*
|
|
1794
|
+
* const val: unknown = { name: "Alice", id: 123 }
|
|
1795
|
+
* if (isPersonAndEmployee(val)) {
|
|
1796
|
+
* // val is narrowed to Person & Employee
|
|
1797
|
+
* assert.strictEqual(val.name, "Alice")
|
|
1798
|
+
* assert.strictEqual(val.id, 123)
|
|
1799
|
+
* }
|
|
1205
1800
|
*
|
|
1206
|
-
* assert.
|
|
1207
|
-
* assert.
|
|
1208
|
-
* assert.deepStrictEqual(length(2)("aaa"), false)
|
|
1801
|
+
* assert.strictEqual(isPersonAndEmployee({ name: "Bob" }), false) // Missing id
|
|
1802
|
+
* assert.strictEqual(isPersonAndEmployee({ id: 456 }), false) // Missing name
|
|
1209
1803
|
* ```
|
|
1210
1804
|
*
|
|
1211
1805
|
* @category combinators
|
|
@@ -1213,21 +1807,34 @@ export const and: {
|
|
|
1213
1807
|
*/
|
|
1214
1808
|
<A, B extends A, C extends A>(self: Refinement<A, B>, that: Refinement<A, C>): Refinement<A, B & C>
|
|
1215
1809
|
/**
|
|
1216
|
-
* Combines two predicates
|
|
1810
|
+
* Combines two predicates with a logical "AND". The resulting predicate returns `true`
|
|
1811
|
+
* only if both of the predicates return `true`.
|
|
1812
|
+
*
|
|
1813
|
+
* If both predicates are `Refinement`s, the resulting predicate is a `Refinement` to the
|
|
1814
|
+
* intersection of their target types (`B & C`).
|
|
1217
1815
|
*
|
|
1218
1816
|
* @example
|
|
1219
1817
|
* ```ts
|
|
1220
1818
|
* import * as assert from "node:assert"
|
|
1221
1819
|
* import { Predicate } from "effect"
|
|
1222
1820
|
*
|
|
1223
|
-
*
|
|
1224
|
-
*
|
|
1821
|
+
* type Person = { name: string }
|
|
1822
|
+
* type Employee = { id: number }
|
|
1823
|
+
*
|
|
1824
|
+
* const hasName = (u: unknown): u is Person => Predicate.hasProperty(u, "name") && typeof (u as any).name === "string"
|
|
1825
|
+
* const hasId = (u: unknown): u is Employee => Predicate.hasProperty(u, "id") && typeof (u as any).id === "number"
|
|
1826
|
+
*
|
|
1827
|
+
* const isPersonAndEmployee = Predicate.and(hasName, hasId)
|
|
1225
1828
|
*
|
|
1226
|
-
* const
|
|
1829
|
+
* const val: unknown = { name: "Alice", id: 123 }
|
|
1830
|
+
* if (isPersonAndEmployee(val)) {
|
|
1831
|
+
* // val is narrowed to Person & Employee
|
|
1832
|
+
* assert.strictEqual(val.name, "Alice")
|
|
1833
|
+
* assert.strictEqual(val.id, 123)
|
|
1834
|
+
* }
|
|
1227
1835
|
*
|
|
1228
|
-
* assert.
|
|
1229
|
-
* assert.
|
|
1230
|
-
* assert.deepStrictEqual(length(2)("aaa"), false)
|
|
1836
|
+
* assert.strictEqual(isPersonAndEmployee({ name: "Bob" }), false) // Missing id
|
|
1837
|
+
* assert.strictEqual(isPersonAndEmployee({ id: 456 }), false) // Missing name
|
|
1231
1838
|
* ```
|
|
1232
1839
|
*
|
|
1233
1840
|
* @category combinators
|
|
@@ -1235,21 +1842,34 @@ export const and: {
|
|
|
1235
1842
|
*/
|
|
1236
1843
|
<A>(that: Predicate<A>): (self: Predicate<A>) => Predicate<A>
|
|
1237
1844
|
/**
|
|
1238
|
-
* Combines two predicates
|
|
1845
|
+
* Combines two predicates with a logical "AND". The resulting predicate returns `true`
|
|
1846
|
+
* only if both of the predicates return `true`.
|
|
1847
|
+
*
|
|
1848
|
+
* If both predicates are `Refinement`s, the resulting predicate is a `Refinement` to the
|
|
1849
|
+
* intersection of their target types (`B & C`).
|
|
1239
1850
|
*
|
|
1240
1851
|
* @example
|
|
1241
1852
|
* ```ts
|
|
1242
1853
|
* import * as assert from "node:assert"
|
|
1243
1854
|
* import { Predicate } from "effect"
|
|
1244
1855
|
*
|
|
1245
|
-
*
|
|
1246
|
-
*
|
|
1856
|
+
* type Person = { name: string }
|
|
1857
|
+
* type Employee = { id: number }
|
|
1858
|
+
*
|
|
1859
|
+
* const hasName = (u: unknown): u is Person => Predicate.hasProperty(u, "name") && typeof (u as any).name === "string"
|
|
1860
|
+
* const hasId = (u: unknown): u is Employee => Predicate.hasProperty(u, "id") && typeof (u as any).id === "number"
|
|
1247
1861
|
*
|
|
1248
|
-
* const
|
|
1862
|
+
* const isPersonAndEmployee = Predicate.and(hasName, hasId)
|
|
1249
1863
|
*
|
|
1250
|
-
*
|
|
1251
|
-
*
|
|
1252
|
-
*
|
|
1864
|
+
* const val: unknown = { name: "Alice", id: 123 }
|
|
1865
|
+
* if (isPersonAndEmployee(val)) {
|
|
1866
|
+
* // val is narrowed to Person & Employee
|
|
1867
|
+
* assert.strictEqual(val.name, "Alice")
|
|
1868
|
+
* assert.strictEqual(val.id, 123)
|
|
1869
|
+
* }
|
|
1870
|
+
*
|
|
1871
|
+
* assert.strictEqual(isPersonAndEmployee({ name: "Bob" }), false) // Missing id
|
|
1872
|
+
* assert.strictEqual(isPersonAndEmployee({ id: 456 }), false) // Missing name
|
|
1253
1873
|
* ```
|
|
1254
1874
|
*
|
|
1255
1875
|
* @category combinators
|
|
@@ -1259,16 +1879,73 @@ export const and: {
|
|
|
1259
1879
|
} = dual(2, <A>(self: Predicate<A>, that: Predicate<A>): Predicate<A> => (a) => self(a) && that(a))
|
|
1260
1880
|
|
|
1261
1881
|
/**
|
|
1882
|
+
* Combines two predicates with a logical "XOR" (exclusive OR). The resulting predicate
|
|
1883
|
+
* returns `true` if one of the predicates returns `true`, but not both.
|
|
1884
|
+
*
|
|
1885
|
+
* @example
|
|
1886
|
+
* ```ts
|
|
1887
|
+
* import * as assert from "node:assert"
|
|
1888
|
+
* import { Predicate } from "effect"
|
|
1889
|
+
*
|
|
1890
|
+
* const isPositive = (n: number) => n > 0
|
|
1891
|
+
* const isEven = (n: number) => n % 2 === 0
|
|
1892
|
+
*
|
|
1893
|
+
* const isPositiveXorEven = Predicate.xor(isPositive, isEven)
|
|
1894
|
+
*
|
|
1895
|
+
* assert.strictEqual(isPositiveXorEven(4), false) // both true -> false
|
|
1896
|
+
* assert.strictEqual(isPositiveXorEven(3), true) // one true -> true
|
|
1897
|
+
* assert.strictEqual(isPositiveXorEven(-2), true) // one true -> true
|
|
1898
|
+
* assert.strictEqual(isPositiveXorEven(-1), false) // both false -> false
|
|
1899
|
+
* ```
|
|
1900
|
+
*
|
|
1262
1901
|
* @category combinators
|
|
1263
1902
|
* @since 2.0.0
|
|
1264
1903
|
*/
|
|
1265
1904
|
export const xor: {
|
|
1266
1905
|
/**
|
|
1906
|
+
* Combines two predicates with a logical "XOR" (exclusive OR). The resulting predicate
|
|
1907
|
+
* returns `true` if one of the predicates returns `true`, but not both.
|
|
1908
|
+
*
|
|
1909
|
+
* @example
|
|
1910
|
+
* ```ts
|
|
1911
|
+
* import * as assert from "node:assert"
|
|
1912
|
+
* import { Predicate } from "effect"
|
|
1913
|
+
*
|
|
1914
|
+
* const isPositive = (n: number) => n > 0
|
|
1915
|
+
* const isEven = (n: number) => n % 2 === 0
|
|
1916
|
+
*
|
|
1917
|
+
* const isPositiveXorEven = Predicate.xor(isPositive, isEven)
|
|
1918
|
+
*
|
|
1919
|
+
* assert.strictEqual(isPositiveXorEven(4), false) // both true -> false
|
|
1920
|
+
* assert.strictEqual(isPositiveXorEven(3), true) // one true -> true
|
|
1921
|
+
* assert.strictEqual(isPositiveXorEven(-2), true) // one true -> true
|
|
1922
|
+
* assert.strictEqual(isPositiveXorEven(-1), false) // both false -> false
|
|
1923
|
+
* ```
|
|
1924
|
+
*
|
|
1267
1925
|
* @category combinators
|
|
1268
1926
|
* @since 2.0.0
|
|
1269
1927
|
*/
|
|
1270
1928
|
<A>(that: Predicate<A>): (self: Predicate<A>) => Predicate<A>
|
|
1271
1929
|
/**
|
|
1930
|
+
* Combines two predicates with a logical "XOR" (exclusive OR). The resulting predicate
|
|
1931
|
+
* returns `true` if one of the predicates returns `true`, but not both.
|
|
1932
|
+
*
|
|
1933
|
+
* @example
|
|
1934
|
+
* ```ts
|
|
1935
|
+
* import * as assert from "node:assert"
|
|
1936
|
+
* import { Predicate } from "effect"
|
|
1937
|
+
*
|
|
1938
|
+
* const isPositive = (n: number) => n > 0
|
|
1939
|
+
* const isEven = (n: number) => n % 2 === 0
|
|
1940
|
+
*
|
|
1941
|
+
* const isPositiveXorEven = Predicate.xor(isPositive, isEven)
|
|
1942
|
+
*
|
|
1943
|
+
* assert.strictEqual(isPositiveXorEven(4), false) // both true -> false
|
|
1944
|
+
* assert.strictEqual(isPositiveXorEven(3), true) // one true -> true
|
|
1945
|
+
* assert.strictEqual(isPositiveXorEven(-2), true) // one true -> true
|
|
1946
|
+
* assert.strictEqual(isPositiveXorEven(-1), false) // both false -> false
|
|
1947
|
+
* ```
|
|
1948
|
+
*
|
|
1272
1949
|
* @category combinators
|
|
1273
1950
|
* @since 2.0.0
|
|
1274
1951
|
*/
|
|
@@ -1276,16 +1953,73 @@ export const xor: {
|
|
|
1276
1953
|
} = dual(2, <A>(self: Predicate<A>, that: Predicate<A>): Predicate<A> => (a) => self(a) !== that(a))
|
|
1277
1954
|
|
|
1278
1955
|
/**
|
|
1956
|
+
* Combines two predicates with a logical "EQV" (equivalence). The resulting predicate
|
|
1957
|
+
* returns `true` if both predicates return the same boolean value (both `true` or both `false`).
|
|
1958
|
+
*
|
|
1959
|
+
* @example
|
|
1960
|
+
* ```ts
|
|
1961
|
+
* import * as assert from "node:assert"
|
|
1962
|
+
* import { Predicate } from "effect"
|
|
1963
|
+
*
|
|
1964
|
+
* const isPositive = (n: number) => n > 0
|
|
1965
|
+
* const isEven = (n: number) => n % 2 === 0
|
|
1966
|
+
*
|
|
1967
|
+
* const isPositiveEqvEven = Predicate.eqv(isPositive, isEven)
|
|
1968
|
+
*
|
|
1969
|
+
* assert.strictEqual(isPositiveEqvEven(4), true) // both true -> true
|
|
1970
|
+
* assert.strictEqual(isPositiveEqvEven(3), false) // different -> false
|
|
1971
|
+
* assert.strictEqual(isPositiveEqvEven(-2), false) // different -> false
|
|
1972
|
+
* assert.strictEqual(isPositiveEqvEven(-1), true) // both false -> true
|
|
1973
|
+
* ```
|
|
1974
|
+
*
|
|
1279
1975
|
* @category combinators
|
|
1280
1976
|
* @since 2.0.0
|
|
1281
1977
|
*/
|
|
1282
1978
|
export const eqv: {
|
|
1283
1979
|
/**
|
|
1980
|
+
* Combines two predicates with a logical "EQV" (equivalence). The resulting predicate
|
|
1981
|
+
* returns `true` if both predicates return the same boolean value (both `true` or both `false`).
|
|
1982
|
+
*
|
|
1983
|
+
* @example
|
|
1984
|
+
* ```ts
|
|
1985
|
+
* import * as assert from "node:assert"
|
|
1986
|
+
* import { Predicate } from "effect"
|
|
1987
|
+
*
|
|
1988
|
+
* const isPositive = (n: number) => n > 0
|
|
1989
|
+
* const isEven = (n: number) => n % 2 === 0
|
|
1990
|
+
*
|
|
1991
|
+
* const isPositiveEqvEven = Predicate.eqv(isPositive, isEven)
|
|
1992
|
+
*
|
|
1993
|
+
* assert.strictEqual(isPositiveEqvEven(4), true) // both true -> true
|
|
1994
|
+
* assert.strictEqual(isPositiveEqvEven(3), false) // different -> false
|
|
1995
|
+
* assert.strictEqual(isPositiveEqvEven(-2), false) // different -> false
|
|
1996
|
+
* assert.strictEqual(isPositiveEqvEven(-1), true) // both false -> true
|
|
1997
|
+
* ```
|
|
1998
|
+
*
|
|
1284
1999
|
* @category combinators
|
|
1285
2000
|
* @since 2.0.0
|
|
1286
2001
|
*/
|
|
1287
2002
|
<A>(that: Predicate<A>): (self: Predicate<A>) => Predicate<A>
|
|
1288
2003
|
/**
|
|
2004
|
+
* Combines two predicates with a logical "EQV" (equivalence). The resulting predicate
|
|
2005
|
+
* returns `true` if both predicates return the same boolean value (both `true` or both `false`).
|
|
2006
|
+
*
|
|
2007
|
+
* @example
|
|
2008
|
+
* ```ts
|
|
2009
|
+
* import * as assert from "node:assert"
|
|
2010
|
+
* import { Predicate } from "effect"
|
|
2011
|
+
*
|
|
2012
|
+
* const isPositive = (n: number) => n > 0
|
|
2013
|
+
* const isEven = (n: number) => n % 2 === 0
|
|
2014
|
+
*
|
|
2015
|
+
* const isPositiveEqvEven = Predicate.eqv(isPositive, isEven)
|
|
2016
|
+
*
|
|
2017
|
+
* assert.strictEqual(isPositiveEqvEven(4), true) // both true -> true
|
|
2018
|
+
* assert.strictEqual(isPositiveEqvEven(3), false) // different -> false
|
|
2019
|
+
* assert.strictEqual(isPositiveEqvEven(-2), false) // different -> false
|
|
2020
|
+
* assert.strictEqual(isPositiveEqvEven(-1), true) // both false -> true
|
|
2021
|
+
* ```
|
|
2022
|
+
*
|
|
1289
2023
|
* @category combinators
|
|
1290
2024
|
* @since 2.0.0
|
|
1291
2025
|
*/
|
|
@@ -1293,47 +2027,59 @@ export const eqv: {
|
|
|
1293
2027
|
} = dual(2, <A>(self: Predicate<A>, that: Predicate<A>): Predicate<A> => (a) => self(a) === that(a))
|
|
1294
2028
|
|
|
1295
2029
|
/**
|
|
1296
|
-
*
|
|
1297
|
-
* logic, the implication operator `->` denotes that if the first proposition
|
|
1298
|
-
* (antecedent) is true, then the second proposition (consequent) must also be
|
|
1299
|
-
* true. In simpler terms, `p implies q` can be interpreted as "if p then q". If
|
|
1300
|
-
* the first predicate holds, then the second predicate must hold
|
|
1301
|
-
* for the given context.
|
|
2030
|
+
* Creates a predicate that represents a logical "if-then" rule.
|
|
1302
2031
|
*
|
|
1303
|
-
*
|
|
2032
|
+
* Think of it as a conditional promise: **"If `antecedent` holds true, then I promise `consequent` will also be true."**
|
|
1304
2033
|
*
|
|
1305
|
-
*
|
|
1306
|
-
* because the outcome of the consequent cannot be determined.
|
|
2034
|
+
* This function is invaluable for defining complex validation logic where one condition dictates another.
|
|
1307
2035
|
*
|
|
1308
|
-
*
|
|
1309
|
-
* constraints that are contingent on certain conditions.
|
|
1310
|
-
* It proves especially helpful in defining property tests.
|
|
2036
|
+
* ### How It Works
|
|
1311
2037
|
*
|
|
1312
|
-
* The
|
|
1313
|
-
*
|
|
1314
|
-
*
|
|
2038
|
+
* The rule only fails (returns `false`) when the "if" part is `true`, but the "then" part is `false`.
|
|
2039
|
+
* In all other cases, the promise is considered kept, and the result is `true`.
|
|
2040
|
+
*
|
|
2041
|
+
* This includes the concept of **"vacuous truth"**: if the "if" part is `false`, the rule doesn't apply,
|
|
2042
|
+
* so the promise isn't broken, and the result is `true`. (e.g., "If it rains, I'll bring an umbrella."
|
|
2043
|
+
* If it doesn't rain, you haven't broken your promise, no matter what).
|
|
2044
|
+
*
|
|
2045
|
+
* ### Key Details
|
|
2046
|
+
*
|
|
2047
|
+
* - **Logical Equivalence**: `implies(p, q)` is the same as `not(p).or(q)`, or simply `!p || q`
|
|
2048
|
+
* in plain JavaScript. This can be a helpful way to reason about its behavior.
|
|
2049
|
+
*
|
|
2050
|
+
* - **Type-Safety Warning**: This function always returns a `Predicate`, never a type-narrowing
|
|
2051
|
+
* `Refinement`. A `true` result doesn't guarantee the `consequent` passed (it could be `true`
|
|
2052
|
+
* simply because the `antecedent` was `false`), so it cannot be used to safely narrow a type.
|
|
1315
2053
|
*
|
|
1316
2054
|
* @example
|
|
1317
2055
|
* ```ts
|
|
2056
|
+
* // Rule: A user can only be an admin if they also belong to the "staff" group.
|
|
1318
2057
|
* import * as assert from "node:assert"
|
|
1319
2058
|
* import { Predicate } from "effect"
|
|
1320
2059
|
*
|
|
1321
|
-
* type
|
|
1322
|
-
*
|
|
1323
|
-
*
|
|
1324
|
-
* readonly c: number
|
|
2060
|
+
* type User = {
|
|
2061
|
+
* isStaff: boolean
|
|
2062
|
+
* isAdmin: boolean
|
|
1325
2063
|
* }
|
|
1326
2064
|
*
|
|
1327
|
-
* const
|
|
1328
|
-
* // antecedent
|
|
1329
|
-
* (
|
|
1330
|
-
* // consequent
|
|
1331
|
-
* (
|
|
2065
|
+
* const isValidUserPermission = Predicate.implies(
|
|
2066
|
+
* // antecedent: "if" the user is an admin...
|
|
2067
|
+
* (user: User) => user.isAdmin,
|
|
2068
|
+
* // consequent: "then" they must be staff.
|
|
2069
|
+
* (user: User) => user.isStaff
|
|
1332
2070
|
* )
|
|
1333
2071
|
*
|
|
1334
|
-
*
|
|
1335
|
-
*
|
|
1336
|
-
*
|
|
2072
|
+
* // A non-admin who is not staff. Rule doesn't apply (antecedent is false).
|
|
2073
|
+
* assert.strictEqual(isValidUserPermission({ isStaff: false, isAdmin: false }), true)
|
|
2074
|
+
*
|
|
2075
|
+
* // A staff member who is not an admin. Rule doesn't apply (antecedent is false).
|
|
2076
|
+
* assert.strictEqual(isValidUserPermission({ isStaff: true, isAdmin: false }), true)
|
|
2077
|
+
*
|
|
2078
|
+
* // An admin who is also staff. The rule was followed.
|
|
2079
|
+
* assert.strictEqual(isValidUserPermission({ isStaff: true, isAdmin: true }), true)
|
|
2080
|
+
*
|
|
2081
|
+
* // An admin who is NOT staff. The rule was broken!
|
|
2082
|
+
* assert.strictEqual(isValidUserPermission({ isStaff: false, isAdmin: true }), false)
|
|
1337
2083
|
* ```
|
|
1338
2084
|
*
|
|
1339
2085
|
* @category combinators
|
|
@@ -1341,47 +2087,59 @@ export const eqv: {
|
|
|
1341
2087
|
*/
|
|
1342
2088
|
export const implies: {
|
|
1343
2089
|
/**
|
|
1344
|
-
*
|
|
1345
|
-
* logic, the implication operator `->` denotes that if the first proposition
|
|
1346
|
-
* (antecedent) is true, then the second proposition (consequent) must also be
|
|
1347
|
-
* true. In simpler terms, `p implies q` can be interpreted as "if p then q". If
|
|
1348
|
-
* the first predicate holds, then the second predicate must hold
|
|
1349
|
-
* for the given context.
|
|
2090
|
+
* Creates a predicate that represents a logical "if-then" rule.
|
|
1350
2091
|
*
|
|
1351
|
-
*
|
|
2092
|
+
* Think of it as a conditional promise: **"If `antecedent` holds true, then I promise `consequent` will also be true."**
|
|
1352
2093
|
*
|
|
1353
|
-
*
|
|
1354
|
-
* because the outcome of the consequent cannot be determined.
|
|
2094
|
+
* This function is invaluable for defining complex validation logic where one condition dictates another.
|
|
1355
2095
|
*
|
|
1356
|
-
*
|
|
1357
|
-
* constraints that are contingent on certain conditions.
|
|
1358
|
-
* It proves especially helpful in defining property tests.
|
|
2096
|
+
* ### How It Works
|
|
1359
2097
|
*
|
|
1360
|
-
* The
|
|
1361
|
-
*
|
|
1362
|
-
*
|
|
2098
|
+
* The rule only fails (returns `false`) when the "if" part is `true`, but the "then" part is `false`.
|
|
2099
|
+
* In all other cases, the promise is considered kept, and the result is `true`.
|
|
2100
|
+
*
|
|
2101
|
+
* This includes the concept of **"vacuous truth"**: if the "if" part is `false`, the rule doesn't apply,
|
|
2102
|
+
* so the promise isn't broken, and the result is `true`. (e.g., "If it rains, I'll bring an umbrella."
|
|
2103
|
+
* If it doesn't rain, you haven't broken your promise, no matter what).
|
|
2104
|
+
*
|
|
2105
|
+
* ### Key Details
|
|
2106
|
+
*
|
|
2107
|
+
* - **Logical Equivalence**: `implies(p, q)` is the same as `not(p).or(q)`, or simply `!p || q`
|
|
2108
|
+
* in plain JavaScript. This can be a helpful way to reason about its behavior.
|
|
2109
|
+
*
|
|
2110
|
+
* - **Type-Safety Warning**: This function always returns a `Predicate`, never a type-narrowing
|
|
2111
|
+
* `Refinement`. A `true` result doesn't guarantee the `consequent` passed (it could be `true`
|
|
2112
|
+
* simply because the `antecedent` was `false`), so it cannot be used to safely narrow a type.
|
|
1363
2113
|
*
|
|
1364
2114
|
* @example
|
|
1365
2115
|
* ```ts
|
|
2116
|
+
* // Rule: A user can only be an admin if they also belong to the "staff" group.
|
|
1366
2117
|
* import * as assert from "node:assert"
|
|
1367
2118
|
* import { Predicate } from "effect"
|
|
1368
2119
|
*
|
|
1369
|
-
* type
|
|
1370
|
-
*
|
|
1371
|
-
*
|
|
1372
|
-
* readonly c: number
|
|
2120
|
+
* type User = {
|
|
2121
|
+
* isStaff: boolean
|
|
2122
|
+
* isAdmin: boolean
|
|
1373
2123
|
* }
|
|
1374
2124
|
*
|
|
1375
|
-
* const
|
|
1376
|
-
* // antecedent
|
|
1377
|
-
* (
|
|
1378
|
-
* // consequent
|
|
1379
|
-
* (
|
|
2125
|
+
* const isValidUserPermission = Predicate.implies(
|
|
2126
|
+
* // antecedent: "if" the user is an admin...
|
|
2127
|
+
* (user: User) => user.isAdmin,
|
|
2128
|
+
* // consequent: "then" they must be staff.
|
|
2129
|
+
* (user: User) => user.isStaff
|
|
1380
2130
|
* )
|
|
1381
2131
|
*
|
|
1382
|
-
*
|
|
1383
|
-
*
|
|
1384
|
-
*
|
|
2132
|
+
* // A non-admin who is not staff. Rule doesn't apply (antecedent is false).
|
|
2133
|
+
* assert.strictEqual(isValidUserPermission({ isStaff: false, isAdmin: false }), true)
|
|
2134
|
+
*
|
|
2135
|
+
* // A staff member who is not an admin. Rule doesn't apply (antecedent is false).
|
|
2136
|
+
* assert.strictEqual(isValidUserPermission({ isStaff: true, isAdmin: false }), true)
|
|
2137
|
+
*
|
|
2138
|
+
* // An admin who is also staff. The rule was followed.
|
|
2139
|
+
* assert.strictEqual(isValidUserPermission({ isStaff: true, isAdmin: true }), true)
|
|
2140
|
+
*
|
|
2141
|
+
* // An admin who is NOT staff. The rule was broken!
|
|
2142
|
+
* assert.strictEqual(isValidUserPermission({ isStaff: false, isAdmin: true }), false)
|
|
1385
2143
|
* ```
|
|
1386
2144
|
*
|
|
1387
2145
|
* @category combinators
|
|
@@ -1389,47 +2147,59 @@ export const implies: {
|
|
|
1389
2147
|
*/
|
|
1390
2148
|
<A>(consequent: Predicate<A>): (antecedent: Predicate<A>) => Predicate<A>
|
|
1391
2149
|
/**
|
|
1392
|
-
*
|
|
1393
|
-
*
|
|
1394
|
-
*
|
|
1395
|
-
*
|
|
1396
|
-
*
|
|
1397
|
-
* for the given context.
|
|
2150
|
+
* Creates a predicate that represents a logical "if-then" rule.
|
|
2151
|
+
*
|
|
2152
|
+
* Think of it as a conditional promise: **"If `antecedent` holds true, then I promise `consequent` will also be true."**
|
|
2153
|
+
*
|
|
2154
|
+
* This function is invaluable for defining complex validation logic where one condition dictates another.
|
|
1398
2155
|
*
|
|
1399
|
-
*
|
|
2156
|
+
* ### How It Works
|
|
1400
2157
|
*
|
|
1401
|
-
*
|
|
1402
|
-
*
|
|
2158
|
+
* The rule only fails (returns `false`) when the "if" part is `true`, but the "then" part is `false`.
|
|
2159
|
+
* In all other cases, the promise is considered kept, and the result is `true`.
|
|
1403
2160
|
*
|
|
1404
|
-
* This
|
|
1405
|
-
*
|
|
1406
|
-
*
|
|
2161
|
+
* This includes the concept of **"vacuous truth"**: if the "if" part is `false`, the rule doesn't apply,
|
|
2162
|
+
* so the promise isn't broken, and the result is `true`. (e.g., "If it rains, I'll bring an umbrella."
|
|
2163
|
+
* If it doesn't rain, you haven't broken your promise, no matter what).
|
|
1407
2164
|
*
|
|
1408
|
-
*
|
|
1409
|
-
*
|
|
1410
|
-
*
|
|
2165
|
+
* ### Key Details
|
|
2166
|
+
*
|
|
2167
|
+
* - **Logical Equivalence**: `implies(p, q)` is the same as `not(p).or(q)`, or simply `!p || q`
|
|
2168
|
+
* in plain JavaScript. This can be a helpful way to reason about its behavior.
|
|
2169
|
+
*
|
|
2170
|
+
* - **Type-Safety Warning**: This function always returns a `Predicate`, never a type-narrowing
|
|
2171
|
+
* `Refinement`. A `true` result doesn't guarantee the `consequent` passed (it could be `true`
|
|
2172
|
+
* simply because the `antecedent` was `false`), so it cannot be used to safely narrow a type.
|
|
1411
2173
|
*
|
|
1412
2174
|
* @example
|
|
1413
2175
|
* ```ts
|
|
2176
|
+
* // Rule: A user can only be an admin if they also belong to the "staff" group.
|
|
1414
2177
|
* import * as assert from "node:assert"
|
|
1415
2178
|
* import { Predicate } from "effect"
|
|
1416
2179
|
*
|
|
1417
|
-
* type
|
|
1418
|
-
*
|
|
1419
|
-
*
|
|
1420
|
-
* readonly c: number
|
|
2180
|
+
* type User = {
|
|
2181
|
+
* isStaff: boolean
|
|
2182
|
+
* isAdmin: boolean
|
|
1421
2183
|
* }
|
|
1422
2184
|
*
|
|
1423
|
-
* const
|
|
1424
|
-
* // antecedent
|
|
1425
|
-
* (
|
|
1426
|
-
* // consequent
|
|
1427
|
-
* (
|
|
2185
|
+
* const isValidUserPermission = Predicate.implies(
|
|
2186
|
+
* // antecedent: "if" the user is an admin...
|
|
2187
|
+
* (user: User) => user.isAdmin,
|
|
2188
|
+
* // consequent: "then" they must be staff.
|
|
2189
|
+
* (user: User) => user.isStaff
|
|
1428
2190
|
* )
|
|
1429
2191
|
*
|
|
1430
|
-
*
|
|
1431
|
-
*
|
|
1432
|
-
*
|
|
2192
|
+
* // A non-admin who is not staff. Rule doesn't apply (antecedent is false).
|
|
2193
|
+
* assert.strictEqual(isValidUserPermission({ isStaff: false, isAdmin: false }), true)
|
|
2194
|
+
*
|
|
2195
|
+
* // A staff member who is not an admin. Rule doesn't apply (antecedent is false).
|
|
2196
|
+
* assert.strictEqual(isValidUserPermission({ isStaff: true, isAdmin: false }), true)
|
|
2197
|
+
*
|
|
2198
|
+
* // An admin who is also staff. The rule was followed.
|
|
2199
|
+
* assert.strictEqual(isValidUserPermission({ isStaff: true, isAdmin: true }), true)
|
|
2200
|
+
*
|
|
2201
|
+
* // An admin who is NOT staff. The rule was broken!
|
|
2202
|
+
* assert.strictEqual(isValidUserPermission({ isStaff: false, isAdmin: true }), false)
|
|
1433
2203
|
* ```
|
|
1434
2204
|
*
|
|
1435
2205
|
* @category combinators
|
|
@@ -1442,16 +2212,28 @@ export const implies: {
|
|
|
1442
2212
|
)
|
|
1443
2213
|
|
|
1444
2214
|
/**
|
|
2215
|
+
* Combines two predicates with a logical "NOR" (negated OR). The resulting predicate
|
|
2216
|
+
* returns `true` only if both predicates return `false`.
|
|
2217
|
+
* This is equivalent to `not(or(p, q))`.
|
|
2218
|
+
*
|
|
1445
2219
|
* @category combinators
|
|
1446
2220
|
* @since 2.0.0
|
|
1447
2221
|
*/
|
|
1448
2222
|
export const nor: {
|
|
1449
2223
|
/**
|
|
2224
|
+
* Combines two predicates with a logical "NOR" (negated OR). The resulting predicate
|
|
2225
|
+
* returns `true` only if both predicates return `false`.
|
|
2226
|
+
* This is equivalent to `not(or(p, q))`.
|
|
2227
|
+
*
|
|
1450
2228
|
* @category combinators
|
|
1451
2229
|
* @since 2.0.0
|
|
1452
2230
|
*/
|
|
1453
2231
|
<A>(that: Predicate<A>): (self: Predicate<A>) => Predicate<A>
|
|
1454
2232
|
/**
|
|
2233
|
+
* Combines two predicates with a logical "NOR" (negated OR). The resulting predicate
|
|
2234
|
+
* returns `true` only if both predicates return `false`.
|
|
2235
|
+
* This is equivalent to `not(or(p, q))`.
|
|
2236
|
+
*
|
|
1455
2237
|
* @category combinators
|
|
1456
2238
|
* @since 2.0.0
|
|
1457
2239
|
*/
|
|
@@ -1462,16 +2244,28 @@ export const nor: {
|
|
|
1462
2244
|
)
|
|
1463
2245
|
|
|
1464
2246
|
/**
|
|
2247
|
+
* Combines two predicates with a logical "NAND" (negated AND). The resulting predicate
|
|
2248
|
+
* returns `true` if at least one of the predicates returns `false`.
|
|
2249
|
+
* This is equivalent to `not(and(p, q))`.
|
|
2250
|
+
*
|
|
1465
2251
|
* @category combinators
|
|
1466
2252
|
* @since 2.0.0
|
|
1467
2253
|
*/
|
|
1468
2254
|
export const nand: {
|
|
1469
2255
|
/**
|
|
2256
|
+
* Combines two predicates with a logical "NAND" (negated AND). The resulting predicate
|
|
2257
|
+
* returns `true` if at least one of the predicates returns `false`.
|
|
2258
|
+
* This is equivalent to `not(and(p, q))`.
|
|
2259
|
+
*
|
|
1470
2260
|
* @category combinators
|
|
1471
2261
|
* @since 2.0.0
|
|
1472
2262
|
*/
|
|
1473
2263
|
<A>(that: Predicate<A>): (self: Predicate<A>) => Predicate<A>
|
|
1474
2264
|
/**
|
|
2265
|
+
* Combines two predicates with a logical "NAND" (negated AND). The resulting predicate
|
|
2266
|
+
* returns `true` if at least one of the predicates returns `false`.
|
|
2267
|
+
* This is equivalent to `not(and(p, q))`.
|
|
2268
|
+
*
|
|
1475
2269
|
* @category combinators
|
|
1476
2270
|
* @since 2.0.0
|
|
1477
2271
|
*/
|
|
@@ -1482,8 +2276,29 @@ export const nand: {
|
|
|
1482
2276
|
)
|
|
1483
2277
|
|
|
1484
2278
|
/**
|
|
2279
|
+
* Takes an iterable of predicates and returns a new predicate. The new predicate
|
|
2280
|
+
* returns `true` if all predicates in the collection return `true` for a given value.
|
|
2281
|
+
*
|
|
2282
|
+
* This is like `Array.prototype.every` but for a collection of predicates.
|
|
2283
|
+
*
|
|
2284
|
+
* @example
|
|
2285
|
+
* ```ts
|
|
2286
|
+
* import * as assert from "node:assert"
|
|
2287
|
+
* import { Predicate } from "effect"
|
|
2288
|
+
*
|
|
2289
|
+
* const isPositive = (n: number) => n > 0
|
|
2290
|
+
* const isEven = (n: number) => n % 2 === 0
|
|
2291
|
+
*
|
|
2292
|
+
* const isPositiveAndEven = Predicate.every([isPositive, isEven])
|
|
2293
|
+
*
|
|
2294
|
+
* assert.strictEqual(isPositiveAndEven(4), true)
|
|
2295
|
+
* assert.strictEqual(isPositiveAndEven(3), false)
|
|
2296
|
+
* assert.strictEqual(isPositiveAndEven(-2), false)
|
|
2297
|
+
* ```
|
|
2298
|
+
*
|
|
1485
2299
|
* @category elements
|
|
1486
2300
|
* @since 2.0.0
|
|
2301
|
+
* @see some
|
|
1487
2302
|
*/
|
|
1488
2303
|
export const every = <A>(collection: Iterable<Predicate<A>>): Predicate<A> => (a: A) => {
|
|
1489
2304
|
for (const p of collection) {
|
|
@@ -1495,8 +2310,29 @@ export const every = <A>(collection: Iterable<Predicate<A>>): Predicate<A> => (a
|
|
|
1495
2310
|
}
|
|
1496
2311
|
|
|
1497
2312
|
/**
|
|
2313
|
+
* Takes an iterable of predicates and returns a new predicate. The new predicate
|
|
2314
|
+
* returns `true` if at least one predicate in the collection returns `true` for a given value.
|
|
2315
|
+
*
|
|
2316
|
+
* This is like `Array.prototype.some` but for a collection of predicates.
|
|
2317
|
+
*
|
|
2318
|
+
* @example
|
|
2319
|
+
* ```ts
|
|
2320
|
+
* import * as assert from "node:assert"
|
|
2321
|
+
* import { Predicate } from "effect"
|
|
2322
|
+
*
|
|
2323
|
+
* const isNegative = (n: number) => n < 0
|
|
2324
|
+
* const isOdd = (n: number) => n % 2 !== 0
|
|
2325
|
+
*
|
|
2326
|
+
* const isNegativeOrOdd = Predicate.some([isNegative, isOdd])
|
|
2327
|
+
*
|
|
2328
|
+
* assert.strictEqual(isNegativeOrOdd(-2), true) // isNegative is true
|
|
2329
|
+
* assert.strictEqual(isNegativeOrOdd(3), true) // isOdd is true
|
|
2330
|
+
* assert.strictEqual(isNegativeOrOdd(4), false) // both are false
|
|
2331
|
+
* ```
|
|
2332
|
+
*
|
|
1498
2333
|
* @category elements
|
|
1499
2334
|
* @since 2.0.0
|
|
2335
|
+
* @see every
|
|
1500
2336
|
*/
|
|
1501
2337
|
export const some = <A>(collection: Iterable<Predicate<A>>): Predicate<A> => (a) => {
|
|
1502
2338
|
for (const p of collection) {
|