Skip to main content Link Search Menu Expand Document (external link)

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 narrows A to B when it returns true.
  • This module focuses on type-level introspection (Source, Target, Coverage), value-level constructors (strictEquals, struct), and runtime guards for the container shapes declared in MTypes (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 ===, not Equal.equals; suitable for primitives or when reference identity is intended.
  • The returned predicate accepts any supertype B of that.

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 Refinement if at least one field’s predicate is a refinement, otherwise a plain Predicate.
  • 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 (unlike Predicate.isObject, which excludes them).
  • Use when distinguishing primitives from anything else in unknown data.

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.Predicate but lifted into Effect.

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 B for Predicate.Refinement<A, B>.
  • Returns never for Predicate.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> and Predicate.Refinement<A, B> it returns A.
  • 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 returns B.
  • For Predicate.Predicate<A> it returns A (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>