variable / @typed/guard

bind

Runs f on a matched object and adds its matched value under a new key. The key must not already exist. Enumerable getters and proxy traps may execute during the object spread.

Package version
1.0.0-beta.13
Category
Record construction
Since
1.0.0

Import

import { bind } from "@typed/guard";

Signatures

export declare const bind: {
    <O extends object, K extends PropertyKey, B, E2, R2>(key: K, f: GuardInput<O, B, E2, R2>): <G extends GuardInput<any, O, any, any>>(guard: G & RecordOutputConstraint<NoInfer<Guard.Output<G>>> & (K extends NoInfer<Guard.Output<G> extends infer A ? (A extends unknown ? keyof A : never) : never> ? never : unknown)) => Guard<Guard.Input<G>, Guard.Output<G> & {
        [k in K]: B;
    }, Guard.Error<G> | E2, Guard.Services<G> | R2>;
    <G extends GuardInput<any, any, any, any>, K extends PropertyKey, B, E2, R2>(guard: G & RecordOutputConstraint<NoInfer<Guard.Output<G>>>, key: Exclude<K, NoInfer<Guard.Output<G> extends infer O ? (O extends unknown ? keyof O : never) : never>>, f: GuardInput<NoInfer<Guard.Output<G>>, B, E2, R2>): Guard<Guard.Input<G>, Guard.Output<G> & {
        [k in K]: B;
    }, Guard.Error<G> | E2, Guard.Services<G> | R2>;
};

Why

Dependent record construction runs the second Guard only after the base matches, preserves None, and unions both error and service channels.

Ownership and lifetime

Construction acquires no resources; each successful bind creates a fresh plain object and the dependent Effect follows the invocation lifetime.

Examples

import { bind, bindTo, liftPredicate, map } from "@typed/guard"
const base = bindTo(liftPredicate((u: unknown): u is string => typeof u === "string"), "text")
const nonEmptyLength = map(liftPredicate((record: { readonly text: string }) => record.text.length > 0), (record) => record.text.length)
const sized = bind(base, "length", nonEmptyLength)

Source