Predicate overview
Extension to the Effect Predicate module providing type-level utilities for predicates and refinements, an enhanced struct predicate, a strict-equality predicate constructor, and runtime guards for the container/primitive shapes defined in MTypes.
Mental model
Predicate.Predicate<A>is a function(a: A) => boolean.Predicate.Refinement<A, B>is a predicate that narrowsAtoBwhen it returnstrue.- This module focuses on type-level introspection (
Source,Target,Coverage), value-level constructors (strictEquals,struct), and runtime guards for the container shapes declared inMTypes(OverOne,OverTwo,Singleton,Pair, plus primitive vs non-primitive splits and function arity).
Common tasks
- Construct: {@link strictEquals}, {@link struct}
- Introspect at type level: {@link Source}, {@link Target}, {@link Coverage}
- Lift records: {@link PredicatesToSources}, {@link PredicatesToTargets}, {@link PredicatesToCoverages}, {@link SourcesToPredicates}
- Primitive split: {@link isPrimitive}, {@link isNonPrimitive}
- Function arity: {@link isOneArgFunction}, {@link isTwoArgFunction}
- Tuple shapes: {@link isSingleton}, {@link isReadonlySingleton}, {@link isPair}, {@link isReadonlyPair}, {@link isOverOne}, {@link isReadonlyOverOne}, {@link isOverTwo}, {@link isReadonlyOverTwo}
Quickstart
Example (Strict equality and struct refinement)
import { pipe, Array } from "effect"
import * as MPredicate from "@parischap/effect-lib/MPredicate"
// strictEquals
console.log(pipe([1, 2, 3, 2], Array.filter(MPredicate.strictEquals(2)))) // [2, 2]
// struct refinement
type Animal = { readonly name: string; readonly age: number | string }
const isAdult = MPredicate.struct<Animal, { readonly age: (n: unknown) => n is number }>({
age: (n): n is number => typeof n === "number" && n >= 18
})
Table of contents
Constructors
strictEquals
Builds a predicate that tests strict equality (===) against that.
- Use to filter, partition, or match values that must be referentially equal to a fixed value.
- Comparison is
===, notEqual.equals; suitable for primitives or when reference identity is intended. - The returned predicate accepts any supertype
Bofthat.
Example (Filtering with strictEquals)
import { pipe, Array } from "effect"
import * as MPredicate from "@parischap/effect-lib/MPredicate"
console.log(pipe([1, 2, 3, 2, 1], Array.filter(MPredicate.strictEquals(2)))) // [2, 2]
Signature
export declare const strictEquals: <B, A extends B>(that: A) => Predicate.Predicate<B>
struct
Enhanced version of Predicate.struct that supports IDE field completion, allows passing only a subset of the struct fields, and correctly infers a Refinement (instead of a plain Predicate) even when only some fields use refinements.
- Use to validate part of a struct without writing predicates for every field.
- Returns a
Refinementif at least one field’s predicate is a refinement, otherwise a plainPredicate. - Fields not provided are not checked.
Example (Refining a struct on a single field)
import * as MPredicate from "@parischap/effect-lib/MPredicate"
type Person = { readonly name: string; readonly age: number | string }
const hasNumericAge = MPredicate.struct<Person, { readonly age: (n: unknown) => n is number }>({
age: (n): n is number => typeof n === "number"
})
const p: Person = { name: "Alice", age: 30 }
if (hasNumericAge(p)) {
// `p.age` has been narrowed to `number`
console.log(p.age + 1) // 31
}
Signature
export declare const struct: <O extends MTypes.NonPrimitive, F extends Partial<SourcesToPredicates<MTypes.Data<O>>>>(
fields: F
) => [Extract<F[keyof F], MTypes.AnyRefinement>] extends [never]
? Predicate.Predicate<O>
: Predicate.Refinement<
O,
{
readonly [key in keyof O]: key extends keyof F
? F[key] extends MTypes.AnyPredicate
? Target<F[key]> & O[key]
: never
: O[key]
}
>
Guards
isNonPrimitive
Refines an unknown value to a JavaScript non-primitive (record, class instance, array, or function).
- Acts as a type guard narrowing the input to
MTypes.NonPrimitive. - Excludes
null; includes functions (unlikePredicate.isObject, which excludes them). - Use when distinguishing primitives from anything else in
unknowndata.
Example (Splitting primitives from non-primitives)
import * as MPredicate from "@parischap/effect-lib/MPredicate"
console.log(MPredicate.isNonPrimitive({ a: 1 })) // true
console.log(MPredicate.isNonPrimitive(() => 1)) // true
console.log(MPredicate.isNonPrimitive(null)) // false
console.log(MPredicate.isNonPrimitive(42)) // false
Signature
export declare const isNonPrimitive: <A>(input: A) => input is Exclude<A, MTypes.Primitive> & MTypes.NonPrimitive
isOneArgFunction
Refines a function with an unknown number of arguments to one that takes exactly one argument.
- Acts as a type guard checking
f.length === 1. - Useful when working with overloaded callbacks where arity matters.
Example (Detecting a unary callback)
import * as MPredicate from "@parischap/effect-lib/MPredicate"
console.log(MPredicate.isOneArgFunction((n: number) => n + 1)) // true
console.log(MPredicate.isOneArgFunction((a: number, b: number) => a + b)) // false
Signature
export declare const isOneArgFunction: <A, R>(f: (a: A, ...args: ReadonlyArray<any>) => R) => f is (a: A) => R
isOverOne
Refines an Array<A> to an OverOne<A> (a non-empty array).
- Acts as a type guard checking
u.length > 0.
Example (Guarding a non-empty array)
import * as MPredicate from "@parischap/effect-lib/MPredicate"
console.log(MPredicate.isOverOne([5])) // true
console.log(MPredicate.isOverOne([])) // false
Signature
export declare const isOverOne: <A>(u: Array<A>) => u is MTypes.OverOne<A>
isOverTwo
Refines an Array<A> to an OverTwo<A> (an array with at least two elements).
- Acts as a type guard checking
u.length >= 2.
Example (Guarding an array with two or more elements)
import * as MPredicate from "@parischap/effect-lib/MPredicate"
console.log(MPredicate.isOverTwo([5, 6])) // true
console.log(MPredicate.isOverTwo([5])) // false
Signature
export declare const isOverTwo: <A>(u: Array<A>) => u is MTypes.OverTwo<A>
isPair
Refines an Array<A> to a Pair<A, A> (a tuple with exactly two elements).
- Acts as a type guard checking
u.length === 2.
Example (Guarding a pair)
import * as MPredicate from "@parischap/effect-lib/MPredicate"
console.log(MPredicate.isPair([5, 6])) // true
console.log(MPredicate.isPair([5])) // false
Signature
export declare const isPair: <A>(u: Array<A>) => u is MTypes.Pair<A, A>
isPrimitive
Refines an unknown value to a JavaScript primitive (string, number, bigint, boolean, symbol, null, or undefined).
- Acts as a type guard narrowing the input to
MTypes.Primitive. - Defined as the negation of {@link isNonPrimitive}.
Example (Guarding a primitive)
import * as MPredicate from "@parischap/effect-lib/MPredicate"
console.log(MPredicate.isPrimitive(42)) // true
console.log(MPredicate.isPrimitive("hi")) // true
console.log(MPredicate.isPrimitive(null)) // true
console.log(MPredicate.isPrimitive([1, 2])) // false
Signature
export declare const isPrimitive: <A>(input: A) => input is Exclude<A, MTypes.NonPrimitive> & MTypes.Primitive
isReadonlyOverOne
Refines a ReadonlyArray<A> to a ReadonlyOverOne<A> (a non-empty readonly array).
- Acts as a type guard checking
u.length > 0.
Signature
export declare const isReadonlyOverOne: <A>(u: ReadonlyArray<A>) => u is MTypes.ReadonlyOverOne<A>
isReadonlyOverTwo
Refines a ReadonlyArray<A> to a ReadonlyOverTwo<A> (a readonly array with at least two elements).
- Acts as a type guard checking
u.length >= 2.
Signature
export declare const isReadonlyOverTwo: <A>(u: ReadonlyArray<A>) => u is MTypes.ReadonlyOverTwo<A>
isReadonlyPair
Refines a ReadonlyArray<A> to a ReadonlyPair<A, A> (a tuple with exactly two elements).
- Acts as a type guard checking
u.length === 2.
Signature
export declare const isReadonlyPair: <A>(u: ReadonlyArray<A>) => u is MTypes.ReadonlyPair<A, A>
isReadonlySingleton
Refines a ReadonlyArray<A> to a ReadonlySingleton<A> (a tuple with exactly one element).
- Acts as a type guard checking
u.length === 1.
Signature
export declare const isReadonlySingleton: <A>(u: ReadonlyArray<A>) => u is MTypes.ReadonlySingleton<A>
isSingleton
Refines an Array<A> to a Singleton<A> (a tuple with exactly one element).
- Acts as a type guard checking
u.length === 1.
Example (Guarding a singleton)
import * as MPredicate from "@parischap/effect-lib/MPredicate"
console.log(MPredicate.isSingleton([5])) // true
console.log(MPredicate.isSingleton([5, 6])) // false
Signature
export declare const isSingleton: <A>(u: Array<A>) => u is MTypes.Singleton<A>
isTwoArgFunction
Refines a function with an unknown number of arguments to one that takes exactly two arguments.
- Acts as a type guard checking
f.length === 2.
Example (Detecting a binary callback)
import * as MPredicate from "@parischap/effect-lib/MPredicate"
console.log(MPredicate.isTwoArgFunction((a: number, b: number) => a + b)) // true
console.log(MPredicate.isTwoArgFunction((n: number) => n + 1)) // false
Signature
export declare const isTwoArgFunction: <A, B, R>(
f: (a: A, b: B, ...args: ReadonlyArray<any>) => R
) => f is (a: A, b: B) => R
Models
EffectPredicate (interface)
An effectful predicate: a function from Z to Effect<boolean, E, R>.
- Use when the predicate result depends on an effectful computation (I/O, async, etc.).
- Mirrors
Predicate.Predicatebut lifted intoEffect.
Signature
export interface EffectPredicate<in Z, out E, out R> {
(x: Z): Effect.Effect<boolean, E, R>
}
Utility types
Coverage (type alias)
Type utility extracting the type a refinement narrows to, returning never for plain predicates.
- Returns
BforPredicate.Refinement<A, B>. - Returns
neverforPredicate.Predicate<A>(since plain predicates do not narrow). - Useful for computing what a refinement removes from a remaining input space.
Signature
export type Coverage<R extends MTypes.AnyPredicate> = readonly [R] extends readonly [
Predicate.Refinement<infer _, infer A>
]
? A
: never
PredicatesToCoverages (type alias)
Type utility mapping an array/record of predicates to an array/record of their coverages.
Signature
export type PredicatesToCoverages<T extends PredicateArray> = {
readonly [key in keyof T]: Coverage<T[key]>
}
PredicatesToSources (type alias)
Type utility mapping an array/record of predicates to an array/record of their sources.
Signature
export type PredicatesToSources<T extends PredicateArray> = {
readonly [key in keyof T]: Source<T[key]>
}
PredicatesToTargets (type alias)
Type utility mapping an array/record of predicates to an array/record of their targets.
Signature
export type PredicatesToTargets<T extends PredicateArray> = {
readonly [key in keyof T]: Target<T[key]>
}
Source (type alias)
Type utility extracting the source type of a predicate or refinement.
- For
Predicate.Predicate<A>andPredicate.Refinement<A, B>it returnsA. - Useful when generic code must reason about the input of an unknown predicate.
Example (Extracting the source)
import type * as MPredicate from "@parischap/effect-lib/MPredicate"
import type * as Predicate from "effect/Predicate"
type _Source = MPredicate.Source<Predicate.Refinement<unknown, string>> // unknown
Signature
export type Source<R extends MTypes.AnyPredicate> = readonly [R] extends readonly [Predicate.Predicate<infer A>]
? A
: never
SourcesToPredicates (type alias)
Type utility mapping an array/record of values to an array/record of predicates over those values.
Signature
export type SourcesToPredicates<T extends MTypes.NonPrimitive> = {
readonly [key in keyof T]: Predicate.Predicate<T[key]>
}
Target (type alias)
Type utility extracting the narrowed type of a predicate or refinement.
- For
Predicate.Refinement<A, B>it returnsB. - For
Predicate.Predicate<A>it returnsA(no narrowing).
Example (Extracting the target)
import type * as MPredicate from "@parischap/effect-lib/MPredicate"
import type * as Predicate from "effect/Predicate"
type _Target = MPredicate.Target<Predicate.Refinement<unknown, string>> // string
Signature
export type Target<R extends MTypes.AnyPredicate> = readonly [R] extends readonly [
Predicate.Refinement<infer _, infer A>
]
? A
: Source<R>