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