/** * Utilities for creating, transforming, and comparing plain TypeScript objects * (structs). Every function produces a new object — inputs are never mutated. * * ## Mental model * * - **Struct**: A plain JS object with a fixed set of known keys (e.g., * `{ name: string; age: number }`). Not a generic key-value record. * - **Dual API**: Most functions accept arguments in both data-first * (`Struct.pick(obj, keys)`) and data-last (`pipe(obj, Struct.pick(keys))`) * style. * - **Immutability**: All operations return a new object; the original is * never modified. * - **Lambda**: A type-level function interface (`~lambda.in` / `~lambda.out`) * used by {@link map}, {@link mapPick}, and {@link mapOmit} so the compiler * can track how value types change. * - **Evolver pattern**: {@link evolve}, {@link evolveKeys}, and * {@link evolveEntries} let you selectively transform values, keys, or both * while leaving untouched properties unchanged. * * ## Common tasks * * - Access a property in a pipeline → {@link get} * - List string keys with proper types → {@link keys} * - Subset / remove properties → {@link pick}, {@link omit} * - Merge two structs (second wins) → {@link assign} * - Rename keys → {@link renameKeys} * - Transform selected values → {@link evolve} * - Transform selected keys → {@link evolveKeys} * - Transform both keys and values → {@link evolveEntries} * - Map all values with a typed lambda → {@link map}, {@link mapPick}, * {@link mapOmit} * - Compare structs → {@link makeEquivalence}, {@link makeOrder} * - Combine / reduce structs → {@link makeCombiner}, {@link makeReducer} * - Flatten intersection types → {@link Simplify} * - Strip `readonly` modifiers → {@link Mutable} * * ## Gotchas * * - {@link keys} only returns `string` keys; symbol keys are excluded. * - {@link pick} and {@link omit} iterate with `for...in`, which includes * inherited enumerable properties but excludes non-enumerable ones. * - {@link assign} spreads with `...`; property order follows standard * JS spread rules. * - {@link map}, {@link mapPick}, {@link mapOmit} require a {@link Lambda} * value created with {@link lambda}; a plain function won't type-check. * * ## Quickstart * * **Example** (Picking, renaming, and evolving struct properties) * * ```ts * import { pipe, Struct } from "effect" * * const user = { firstName: "Alice", lastName: "Smith", age: 30, admin: false } * * const result = pipe( * user, * Struct.pick(["firstName", "age"]), * Struct.evolve({ age: (n) => n + 1 }), * Struct.renameKeys({ firstName: "name" }) * ) * * console.log(result) // { name: "Alice", age: 31 } * ``` * * ## See also * * - {@link Equivalence} – building equivalence relations for structs * - {@link Order} – ordering structs by their fields * - {@link Combiner} – combining two values of the same type * - {@link Reducer} – combining with an initial value * * @since 2.0.0 */ import * as Combiner from "./Combiner.ts"; import * as Equivalence from "./Equivalence.ts"; import * as order from "./Order.ts"; import * as Reducer from "./Reducer.ts"; /** * Flattens intersection types into a single object type for readability. * * - Use when hovering over a type shows `A & B & C` instead of the merged * shape. * - Purely cosmetic — no runtime effect. * - Preserves `readonly` modifiers; use {@link Mutable} to strip them. * * **Example** (Flattening an intersection) * * ```ts * import type { Struct } from "effect" * * type Original = { a: string } & { b: number } * * // Without Simplify, the type displays as `{ a: string } & { b: number }` * type Simplified = Struct.Simplify * // { a: string; b: number } * ``` * * @see {@link Mutable} – also flattens but removes `readonly` * @see {@link Assign} – merges two types with right-side precedence * * @category Type-Level Programming * @since 4.0.0 */ export type Simplify = { [K in keyof T]: T[K]; } & {}; /** * Removes `readonly` modifiers from all properties of an object type. * * - Use when you need a mutable version of a readonly interface. * - Purely cosmetic at the type level — no runtime effect. * - Also flattens intersections like {@link Simplify}. * * **Example** (Making a readonly type mutable) * * ```ts * import type { Struct } from "effect" * * type ReadOnly = { readonly a: string; readonly b: number } * type Writable = Struct.Mutable * // { a: string; b: number } * ``` * * @see {@link Simplify} – flattens intersections without removing `readonly` * * @category Type-Level Programming * @since 4.0.0 */ export type Mutable = { -readonly [K in keyof T]: T[K]; } & {}; /** * Merges two object types with properties from `U` taking precedence over `T` * on overlapping keys (like `Object.assign` at the type level). * * - Use when you need the type-level equivalent of `{ ...T, ...U }`. * - When no keys overlap, returns a simple intersection for efficiency. * - When keys overlap, the type from `U` wins. * * **Example** (Merging two types with overlapping keys) * * ```ts * import type { Struct } from "effect" * * type A = { a: string; b: number } * type B = { b: boolean; c: string } * type Merged = Struct.Assign * // { a: string; b: boolean; c: string } * ``` * * @see {@link assign} – the runtime equivalent * @see {@link Simplify} – flatten the resulting intersection * * @category Type-Level Programming * @since 4.0.0 */ export type Assign = Simplify & U>; /** * Retrieves the value at `key` from a struct. * * - Use in a pipeline when you need to extract a single property. * - Does not mutate the input. * - The return type is narrowed to `S[K]`. * * **Example** (Extracting a property in a pipeline) * * ```ts * import { pipe, Struct } from "effect" * * const name = pipe({ name: "Alice", age: 30 }, Struct.get("name")) * console.log(name) // "Alice" * ``` * * @see {@link keys} – list all string keys of a struct * @see {@link pick} – extract multiple properties into a new struct * * @category Getters * @since 2.0.0 */ export declare const get: { /** * Retrieves the value at `key` from a struct. * * - Use in a pipeline when you need to extract a single property. * - Does not mutate the input. * - The return type is narrowed to `S[K]`. * * **Example** (Extracting a property in a pipeline) * * ```ts * import { pipe, Struct } from "effect" * * const name = pipe({ name: "Alice", age: 30 }, Struct.get("name")) * console.log(name) // "Alice" * ``` * * @see {@link keys} – list all string keys of a struct * @see {@link pick} – extract multiple properties into a new struct * * @category Getters * @since 2.0.0 */ (key: K): (self: S) => S[K]; /** * Retrieves the value at `key` from a struct. * * - Use in a pipeline when you need to extract a single property. * - Does not mutate the input. * - The return type is narrowed to `S[K]`. * * **Example** (Extracting a property in a pipeline) * * ```ts * import { pipe, Struct } from "effect" * * const name = pipe({ name: "Alice", age: 30 }, Struct.get("name")) * console.log(name) // "Alice" * ``` * * @see {@link keys} – list all string keys of a struct * @see {@link pick} – extract multiple properties into a new struct * * @category Getters * @since 2.0.0 */ (self: S, key: K): S[K]; }; /** * Returns the string keys of a struct as a properly typed `Array`. * * - Use instead of `Object.keys` when you want the return type narrowed to the * known keys of the struct. * - Symbol keys are excluded; only string keys are returned. * - Does not mutate the input. * * **Example** (Typed keys) * * ```ts * import { Struct } from "effect" * * const user = { name: "Alice", age: 30, [Symbol.for("id")]: 1 } * * const k: Array<"name" | "age"> = Struct.keys(user) * console.log(k) // ["name", "age"] * ``` * * @see {@link get} – access a single key's value * @see {@link pick} – select a subset of keys into a new struct * * @category Key utilities * @since 3.6.0 */ export declare const keys: (self: S) => Array<(keyof S) & string>; /** * Creates a new struct containing only the specified keys. * * - Use to narrow a struct down to a subset of its properties. * - Does not mutate the input; returns a fresh object. * - Keys not present in the struct are silently ignored. * * **Example** (Selecting specific properties) * * ```ts * import { pipe, Struct } from "effect" * * const user = { name: "Alice", age: 30, admin: true } * const nameAndAge = pipe(user, Struct.pick(["name", "age"])) * console.log(nameAndAge) // { name: "Alice", age: 30 } * ``` * * @see {@link omit} – the inverse (exclude keys instead) * @see {@link get} – extract a single value * * @category filtering * @since 2.0.0 */ export declare const pick: { /** * Creates a new struct containing only the specified keys. * * - Use to narrow a struct down to a subset of its properties. * - Does not mutate the input; returns a fresh object. * - Keys not present in the struct are silently ignored. * * **Example** (Selecting specific properties) * * ```ts * import { pipe, Struct } from "effect" * * const user = { name: "Alice", age: 30, admin: true } * const nameAndAge = pipe(user, Struct.pick(["name", "age"])) * console.log(nameAndAge) // { name: "Alice", age: 30 } * ``` * * @see {@link omit} – the inverse (exclude keys instead) * @see {@link get} – extract a single value * * @category filtering * @since 2.0.0 */ >(keys: Keys): (self: S) => Simplify>; /** * Creates a new struct containing only the specified keys. * * - Use to narrow a struct down to a subset of its properties. * - Does not mutate the input; returns a fresh object. * - Keys not present in the struct are silently ignored. * * **Example** (Selecting specific properties) * * ```ts * import { pipe, Struct } from "effect" * * const user = { name: "Alice", age: 30, admin: true } * const nameAndAge = pipe(user, Struct.pick(["name", "age"])) * console.log(nameAndAge) // { name: "Alice", age: 30 } * ``` * * @see {@link omit} – the inverse (exclude keys instead) * @see {@link get} – extract a single value * * @category filtering * @since 2.0.0 */ >(self: S, keys: Keys): Simplify>; }; /** * Creates a new struct with the specified keys removed. * * - Use to exclude sensitive or irrelevant fields from a struct. * - Does not mutate the input; returns a fresh object. * - Keys not present in the struct are silently ignored. * * **Example** (Removing a property) * * ```ts * import { pipe, Struct } from "effect" * * const user = { name: "Alice", age: 30, password: "secret" } * const safe = pipe(user, Struct.omit(["password"])) * console.log(safe) // { name: "Alice", age: 30 } * ``` * * @see {@link pick} – the inverse (keep only specified keys) * * @category filtering * @since 2.0.0 */ export declare const omit: { /** * Creates a new struct with the specified keys removed. * * - Use to exclude sensitive or irrelevant fields from a struct. * - Does not mutate the input; returns a fresh object. * - Keys not present in the struct are silently ignored. * * **Example** (Removing a property) * * ```ts * import { pipe, Struct } from "effect" * * const user = { name: "Alice", age: 30, password: "secret" } * const safe = pipe(user, Struct.omit(["password"])) * console.log(safe) // { name: "Alice", age: 30 } * ``` * * @see {@link pick} – the inverse (keep only specified keys) * * @category filtering * @since 2.0.0 */ >(keys: Keys): (self: S) => Simplify>; /** * Creates a new struct with the specified keys removed. * * - Use to exclude sensitive or irrelevant fields from a struct. * - Does not mutate the input; returns a fresh object. * - Keys not present in the struct are silently ignored. * * **Example** (Removing a property) * * ```ts * import { pipe, Struct } from "effect" * * const user = { name: "Alice", age: 30, password: "secret" } * const safe = pipe(user, Struct.omit(["password"])) * console.log(safe) // { name: "Alice", age: 30 } * ``` * * @see {@link pick} – the inverse (keep only specified keys) * * @category filtering * @since 2.0.0 */ >(self: S, keys: Keys): Simplify>; }; /** * Merges two structs into a new struct. When both structs share a key, the * value from `that` (the second struct) wins. * * - Use when you want `{ ...self, ...that }` with proper types. * - Does not mutate either input; returns a fresh object. * - The result type is `Simplify>`. * * **Example** (Merging structs with overlapping keys) * * ```ts * import { pipe, Struct } from "effect" * * const defaults = { theme: "light", lang: "en" } * const overrides = { theme: "dark", fontSize: 14 } * const config = pipe(defaults, Struct.assign(overrides)) * console.log(config) // { theme: "dark", lang: "en", fontSize: 14 } * ``` * * @see {@link Assign} – the type-level equivalent * @see {@link evolve} – transform individual values instead of replacing them * * @category combining * @since 4.0.0 */ export declare const assign: { /** * Merges two structs into a new struct. When both structs share a key, the * value from `that` (the second struct) wins. * * - Use when you want `{ ...self, ...that }` with proper types. * - Does not mutate either input; returns a fresh object. * - The result type is `Simplify>`. * * **Example** (Merging structs with overlapping keys) * * ```ts * import { pipe, Struct } from "effect" * * const defaults = { theme: "light", lang: "en" } * const overrides = { theme: "dark", fontSize: 14 } * const config = pipe(defaults, Struct.assign(overrides)) * console.log(config) // { theme: "dark", lang: "en", fontSize: 14 } * ``` * * @see {@link Assign} – the type-level equivalent * @see {@link evolve} – transform individual values instead of replacing them * * @category combining * @since 4.0.0 */ (that: O): (self: S) => Assign; /** * Merges two structs into a new struct. When both structs share a key, the * value from `that` (the second struct) wins. * * - Use when you want `{ ...self, ...that }` with proper types. * - Does not mutate either input; returns a fresh object. * - The result type is `Simplify>`. * * **Example** (Merging structs with overlapping keys) * * ```ts * import { pipe, Struct } from "effect" * * const defaults = { theme: "light", lang: "en" } * const overrides = { theme: "dark", fontSize: 14 } * const config = pipe(defaults, Struct.assign(overrides)) * console.log(config) // { theme: "dark", lang: "en", fontSize: 14 } * ``` * * @see {@link Assign} – the type-level equivalent * @see {@link evolve} – transform individual values instead of replacing them * * @category combining * @since 4.0.0 */ (self: S, that: O): Assign; }; type Evolver = { readonly [K in keyof S]?: (a: S[K]) => unknown; }; type Evolved = Simplify<{ [K in keyof S]: K extends keyof E ? (E[K] extends (...a: any) => infer R ? R : S[K]) : S[K]; }>; /** * Selectively transforms values of a struct using per-key functions. Keys * without a corresponding function are copied unchanged. * * - Use when you want to update specific fields while keeping the rest intact. * - Does not mutate the input; returns a fresh object. * - Each transform function receives the current value and returns the new * value; the return type can differ from the input type. * * **Example** (Transforming selected values) * * ```ts * import { pipe, Struct } from "effect" * * const result = pipe( * { name: "alice", age: 30, active: true }, * Struct.evolve({ * name: (s) => s.toUpperCase(), * age: (n) => n + 1 * }) * ) * console.log(result) // { name: "ALICE", age: 31, active: true } * ``` * * @see {@link evolveKeys} – transform keys instead of values * @see {@link evolveEntries} – transform both keys and values * @see {@link map} – apply the same transformation to all values * * @category transforming * @since 2.0.0 */ export declare const evolve: { /** * Selectively transforms values of a struct using per-key functions. Keys * without a corresponding function are copied unchanged. * * - Use when you want to update specific fields while keeping the rest intact. * - Does not mutate the input; returns a fresh object. * - Each transform function receives the current value and returns the new * value; the return type can differ from the input type. * * **Example** (Transforming selected values) * * ```ts * import { pipe, Struct } from "effect" * * const result = pipe( * { name: "alice", age: 30, active: true }, * Struct.evolve({ * name: (s) => s.toUpperCase(), * age: (n) => n + 1 * }) * ) * console.log(result) // { name: "ALICE", age: 31, active: true } * ``` * * @see {@link evolveKeys} – transform keys instead of values * @see {@link evolveEntries} – transform both keys and values * @see {@link map} – apply the same transformation to all values * * @category transforming * @since 2.0.0 */ >(e: E): (self: S) => Evolved; /** * Selectively transforms values of a struct using per-key functions. Keys * without a corresponding function are copied unchanged. * * - Use when you want to update specific fields while keeping the rest intact. * - Does not mutate the input; returns a fresh object. * - Each transform function receives the current value and returns the new * value; the return type can differ from the input type. * * **Example** (Transforming selected values) * * ```ts * import { pipe, Struct } from "effect" * * const result = pipe( * { name: "alice", age: 30, active: true }, * Struct.evolve({ * name: (s) => s.toUpperCase(), * age: (n) => n + 1 * }) * ) * console.log(result) // { name: "ALICE", age: 31, active: true } * ``` * * @see {@link evolveKeys} – transform keys instead of values * @see {@link evolveEntries} – transform both keys and values * @see {@link map} – apply the same transformation to all values * * @category transforming * @since 2.0.0 */ >(self: S, e: E): Evolved; }; type KeyEvolver = { readonly [K in keyof S]?: (k: K) => PropertyKey; }; type KeyEvolved = Simplify<{ [K in keyof S as K extends keyof E ? (E[K] extends ((k: K) => infer R extends PropertyKey) ? R : K) : K]: S[K]; }>; /** * Selectively transforms keys of a struct using per-key functions. Keys without * a corresponding function are copied unchanged. * * - Use when you need computed key names (e.g., uppercasing, prefixing). * - Each transform function receives the key name and must return a new * `PropertyKey`. * - Does not mutate the input; returns a fresh object. * * **Example** (Renaming keys with functions) * * ```ts * import { pipe, Struct } from "effect" * * const result = pipe( * { name: "Alice", age: 30 }, * Struct.evolveKeys({ * name: (k) => k.toUpperCase() * }) * ) * console.log(result) // { NAME: "Alice", age: 30 } * ``` * * @see {@link renameKeys} – rename keys with a static mapping * @see {@link evolve} – transform values instead of keys * @see {@link evolveEntries} – transform both keys and values * * @category Key utilities * @since 4.0.0 */ export declare const evolveKeys: { /** * Selectively transforms keys of a struct using per-key functions. Keys without * a corresponding function are copied unchanged. * * - Use when you need computed key names (e.g., uppercasing, prefixing). * - Each transform function receives the key name and must return a new * `PropertyKey`. * - Does not mutate the input; returns a fresh object. * * **Example** (Renaming keys with functions) * * ```ts * import { pipe, Struct } from "effect" * * const result = pipe( * { name: "Alice", age: 30 }, * Struct.evolveKeys({ * name: (k) => k.toUpperCase() * }) * ) * console.log(result) // { NAME: "Alice", age: 30 } * ``` * * @see {@link renameKeys} – rename keys with a static mapping * @see {@link evolve} – transform values instead of keys * @see {@link evolveEntries} – transform both keys and values * * @category Key utilities * @since 4.0.0 */ >(e: E): (self: S) => KeyEvolved; /** * Selectively transforms keys of a struct using per-key functions. Keys without * a corresponding function are copied unchanged. * * - Use when you need computed key names (e.g., uppercasing, prefixing). * - Each transform function receives the key name and must return a new * `PropertyKey`. * - Does not mutate the input; returns a fresh object. * * **Example** (Renaming keys with functions) * * ```ts * import { pipe, Struct } from "effect" * * const result = pipe( * { name: "Alice", age: 30 }, * Struct.evolveKeys({ * name: (k) => k.toUpperCase() * }) * ) * console.log(result) // { NAME: "Alice", age: 30 } * ``` * * @see {@link renameKeys} – rename keys with a static mapping * @see {@link evolve} – transform values instead of keys * @see {@link evolveEntries} – transform both keys and values * * @category Key utilities * @since 4.0.0 */ >(self: S, e: E): KeyEvolved; }; type EntryEvolver = { readonly [K in keyof S]?: (k: K, v: S[K]) => [PropertyKey, unknown]; }; type EntryEvolved = { [K in keyof S as K extends keyof E ? E[K] extends ((k: K, v: S[K]) => [infer NK extends PropertyKey, infer _V]) ? NK : K : K]: K extends keyof E ? E[K] extends ((k: K, v: S[K]) => [infer _NK, infer V]) ? V : S[K] : S[K]; }; /** * Selectively transforms both keys and values of a struct. Each per-key * function receives `(key, value)` and must return a `[newKey, newValue]` * tuple. Keys without a corresponding function are copied unchanged. * * - Use when you need to rename a key and change its value in one step. * - Does not mutate the input; returns a fresh object. * - The return type is fully tracked at the type level. * * **Example** (Transforming keys and values together) * * ```ts * import { pipe, Struct } from "effect" * * const result = pipe( * { amount: 100, label: "total" }, * Struct.evolveEntries({ * amount: (k, v) => [`${k}Cents`, v * 100], * label: (k, v) => [k, v.toUpperCase()] * }) * ) * console.log(result) // { amountCents: 10000, label: "TOTAL" } * ``` * * @see {@link evolve} – transform values only * @see {@link evolveKeys} – transform keys only * * @category Utilities * @since 4.0.0 */ export declare const evolveEntries: { /** * Selectively transforms both keys and values of a struct. Each per-key * function receives `(key, value)` and must return a `[newKey, newValue]` * tuple. Keys without a corresponding function are copied unchanged. * * - Use when you need to rename a key and change its value in one step. * - Does not mutate the input; returns a fresh object. * - The return type is fully tracked at the type level. * * **Example** (Transforming keys and values together) * * ```ts * import { pipe, Struct } from "effect" * * const result = pipe( * { amount: 100, label: "total" }, * Struct.evolveEntries({ * amount: (k, v) => [`${k}Cents`, v * 100], * label: (k, v) => [k, v.toUpperCase()] * }) * ) * console.log(result) // { amountCents: 10000, label: "TOTAL" } * ``` * * @see {@link evolve} – transform values only * @see {@link evolveKeys} – transform keys only * * @category Utilities * @since 4.0.0 */ >(e: E): (self: S) => EntryEvolved; /** * Selectively transforms both keys and values of a struct. Each per-key * function receives `(key, value)` and must return a `[newKey, newValue]` * tuple. Keys without a corresponding function are copied unchanged. * * - Use when you need to rename a key and change its value in one step. * - Does not mutate the input; returns a fresh object. * - The return type is fully tracked at the type level. * * **Example** (Transforming keys and values together) * * ```ts * import { pipe, Struct } from "effect" * * const result = pipe( * { amount: 100, label: "total" }, * Struct.evolveEntries({ * amount: (k, v) => [`${k}Cents`, v * 100], * label: (k, v) => [k, v.toUpperCase()] * }) * ) * console.log(result) // { amountCents: 10000, label: "TOTAL" } * ``` * * @see {@link evolve} – transform values only * @see {@link evolveKeys} – transform keys only * * @category Utilities * @since 4.0.0 */ >(self: S, e: E): EntryEvolved; }; /** * Renames keys in a struct using a static `{ oldKey: newKey }` mapping. Keys * not mentioned in the mapping are copied unchanged. * * - Use for simple, declarative key renaming without custom logic. * - Does not mutate the input; returns a fresh object. * - For computed key names, use {@link evolveKeys} instead. * * **Example** (Renaming keys) * * ```ts * import { pipe, Struct } from "effect" * * const result = pipe( * { firstName: "Alice", lastName: "Smith", age: 30 }, * Struct.renameKeys({ firstName: "first", lastName: "last" }) * ) * console.log(result) // { first: "Alice", last: "Smith", age: 30 } * ``` * * @see {@link evolveKeys} – rename keys using functions * @see {@link evolveEntries} – rename keys and transform values * * @category Key utilities * @since 4.0.0 */ export declare const renameKeys: { /** * Renames keys in a struct using a static `{ oldKey: newKey }` mapping. Keys * not mentioned in the mapping are copied unchanged. * * - Use for simple, declarative key renaming without custom logic. * - Does not mutate the input; returns a fresh object. * - For computed key names, use {@link evolveKeys} instead. * * **Example** (Renaming keys) * * ```ts * import { pipe, Struct } from "effect" * * const result = pipe( * { firstName: "Alice", lastName: "Smith", age: 30 }, * Struct.renameKeys({ firstName: "first", lastName: "last" }) * ) * console.log(result) // { first: "Alice", last: "Smith", age: 30 } * ``` * * @see {@link evolveKeys} – rename keys using functions * @see {@link evolveEntries} – rename keys and transform values * * @category Key utilities * @since 4.0.0 */ (mapping: M): (self: S) => { [K in keyof S as K extends keyof M ? M[K] extends PropertyKey ? M[K] : K : K]: S[K]; }; /** * Renames keys in a struct using a static `{ oldKey: newKey }` mapping. Keys * not mentioned in the mapping are copied unchanged. * * - Use for simple, declarative key renaming without custom logic. * - Does not mutate the input; returns a fresh object. * - For computed key names, use {@link evolveKeys} instead. * * **Example** (Renaming keys) * * ```ts * import { pipe, Struct } from "effect" * * const result = pipe( * { firstName: "Alice", lastName: "Smith", age: 30 }, * Struct.renameKeys({ firstName: "first", lastName: "last" }) * ) * console.log(result) // { first: "Alice", last: "Smith", age: 30 } * ``` * * @see {@link evolveKeys} – rename keys using functions * @see {@link evolveEntries} – rename keys and transform values * * @category Key utilities * @since 4.0.0 */ (self: S, mapping: M): { [K in keyof S as K extends keyof M ? M[K] extends PropertyKey ? M[K] : K : K]: S[K]; }; }; /** * Creates an `Equivalence` for a struct by providing an `Equivalence` for each * property. Two structs are equivalent when all their corresponding properties * are equivalent. * * Alias of `Equivalence.Struct`. * * - Use when you need to compare structs property-by-property. * - Each property's equivalence is checked independently; all must return * `true` for the overall result to be `true`. * * **Example** (Comparing structs for equivalence) * * ```ts * import { Equivalence, Struct } from "effect" * * const PersonEquivalence = Struct.makeEquivalence({ * name: Equivalence.strictEqual(), * age: Equivalence.strictEqual() * }) * * console.log(PersonEquivalence({ name: "Alice", age: 30 }, { name: "Alice", age: 30 })) * // true * console.log(PersonEquivalence({ name: "Alice", age: 30 }, { name: "Bob", age: 30 })) * // false * ``` * * @see {@link makeOrder} – create an `Order` for structs * * @category Equivalence * @since 2.0.0 */ export declare const makeEquivalence: typeof Equivalence.Struct; /** * Creates an `Order` for a struct by providing an `Order` for each property. * Properties are compared in the order they appear in the fields object; the * first non-zero comparison determines the result. * * Alias of `Order.Struct`. * * - Use to sort or compare structs by multiple fields with lexicographic * priority. * - The order of keys in the `fields` object determines comparison priority. * * **Example** (Ordering structs by name then age) * * ```ts * import { Number, String, Struct } from "effect" * * const PersonOrder = Struct.makeOrder({ * name: String.Order, * age: Number.Order * }) * * console.log(PersonOrder({ name: "Alice", age: 30 }, { name: "Bob", age: 25 })) * // -1 (Alice comes before Bob) * ``` * * @see {@link makeEquivalence} – create an `Equivalence` for structs * * @category Ordering * @since 2.0.0 */ export declare const makeOrder: typeof order.Struct; /** * Interface for type-level functions used by {@link map}, {@link mapPick}, and * {@link mapOmit}. * * - Extend this interface with concrete `~lambda.in` and `~lambda.out` types * to describe how a function transforms values at the type level. * - At runtime, create lambda values with {@link lambda}. * * **Example** (Defining a lambda type) * * ```ts * import type { Struct } from "effect" * * interface ToString extends Struct.Lambda { * readonly "~lambda.out": string * } * ``` * * @see {@link Apply} – apply a Lambda to a concrete type * @see {@link lambda} – create a runtime lambda value * @see {@link map} – use a lambda to transform all struct values * * @category Lambda * @since 4.0.0 */ export interface Lambda { readonly "~lambda.in": unknown; readonly "~lambda.out": unknown; } /** * Applies a {@link Lambda} type-level function to a value type `V`, producing * the output type. * * - Use this when you need to compute what type a Lambda would produce for a * given input. * - Works by intersecting the Lambda with `{ "~lambda.in": V }` and reading * `"~lambda.out"`. * * **Example** (Computing the output type of a lambda) * * ```ts * import type { Struct } from "effect" * * interface ToString extends Struct.Lambda { * readonly "~lambda.out": string * } * * // Result is `string` * type Result = Struct.Apply * ``` * * @see {@link Lambda} – the base interface * * @category Lambda * @since 4.0.0 */ export type Apply = (L & { readonly "~lambda.in": V; })["~lambda.out"]; /** * Wraps a plain function as a {@link Lambda} value so it can be used with * {@link map}, {@link mapPick}, and {@link mapOmit}. * * - The type parameter `L` encodes both the input and output types at the type * level, allowing the compiler to track how struct value types change. * - At runtime, the returned value is the same function — `lambda` only * adjusts the type. * * **Example** (Wrapping values in arrays) * * ```ts * import { pipe, Struct } from "effect" * * interface AsArray extends Struct.Lambda { * (self: A): Array * readonly "~lambda.out": Array * } * * const asArray = Struct.lambda((a) => [a]) * const result = pipe({ x: 1, y: "hello" }, Struct.map(asArray)) * console.log(result) // { x: [1], y: ["hello"] } * ``` * * @see {@link Lambda} – the type-level interface * @see {@link map} – apply a lambda to all struct values * * @category Lambda * @since 4.0.0 */ export declare const lambda: any>(f: (a: Parameters[0]) => ReturnType) => L; /** * Applies a {@link Lambda} transformation to every value in a struct. * * - Use when you want to apply the same function to every value in a struct. * - The lambda must be created with {@link lambda} so the compiler can track * the output types. * - Does not mutate the input; returns a fresh object. * * **Example** (Wrapping every value in an array) * * ```ts * import { pipe, Struct } from "effect" * * interface AsArray extends Struct.Lambda { * (self: A): Array * readonly "~lambda.out": Array * } * * const asArray = Struct.lambda((a) => [a]) * const result = pipe({ width: 10, height: 20 }, Struct.map(asArray)) * console.log(result) // { width: [10], height: [20] } * ``` * * @see {@link mapPick} – apply a lambda only to selected keys * @see {@link mapOmit} – apply a lambda to all keys except selected ones * @see {@link evolve} – apply different functions to different keys * * @category Mapping * @since 4.0.0 */ export declare const map: { /** * Applies a {@link Lambda} transformation to every value in a struct. * * - Use when you want to apply the same function to every value in a struct. * - The lambda must be created with {@link lambda} so the compiler can track * the output types. * - Does not mutate the input; returns a fresh object. * * **Example** (Wrapping every value in an array) * * ```ts * import { pipe, Struct } from "effect" * * interface AsArray extends Struct.Lambda { * (self: A): Array * readonly "~lambda.out": Array * } * * const asArray = Struct.lambda((a) => [a]) * const result = pipe({ width: 10, height: 20 }, Struct.map(asArray)) * console.log(result) // { width: [10], height: [20] } * ``` * * @see {@link mapPick} – apply a lambda only to selected keys * @see {@link mapOmit} – apply a lambda to all keys except selected ones * @see {@link evolve} – apply different functions to different keys * * @category Mapping * @since 4.0.0 */ (lambda: L): (self: S) => { [K in keyof S]: Apply; }; /** * Applies a {@link Lambda} transformation to every value in a struct. * * - Use when you want to apply the same function to every value in a struct. * - The lambda must be created with {@link lambda} so the compiler can track * the output types. * - Does not mutate the input; returns a fresh object. * * **Example** (Wrapping every value in an array) * * ```ts * import { pipe, Struct } from "effect" * * interface AsArray extends Struct.Lambda { * (self: A): Array * readonly "~lambda.out": Array * } * * const asArray = Struct.lambda((a) => [a]) * const result = pipe({ width: 10, height: 20 }, Struct.map(asArray)) * console.log(result) // { width: [10], height: [20] } * ``` * * @see {@link mapPick} – apply a lambda only to selected keys * @see {@link mapOmit} – apply a lambda to all keys except selected ones * @see {@link evolve} – apply different functions to different keys * * @category Mapping * @since 4.0.0 */ (self: S, lambda: L): { [K in keyof S]: Apply; }; }; /** * Applies a {@link Lambda} transformation only to the specified keys; all * other keys are copied unchanged. * * - Use when you want to apply the same transformation to a subset of * properties. * - Does not mutate the input; returns a fresh object. * * **Example** (Wrapping only selected values in arrays) * * ```ts * import { pipe, Struct } from "effect" * * interface AsArray extends Struct.Lambda { * (self: A): Array * readonly "~lambda.out": Array * } * * const asArray = Struct.lambda((a) => [a]) * const result = pipe( * { x: 1, y: 2, z: 3 }, * Struct.mapPick(["x", "z"], asArray) * ) * console.log(result) // { x: [1], y: 2, z: [3] } * ``` * * @see {@link map} – apply a lambda to all keys * @see {@link mapOmit} – apply a lambda to all keys except selected ones * * @category Mapping * @since 4.0.0 */ export declare const mapPick: { /** * Applies a {@link Lambda} transformation only to the specified keys; all * other keys are copied unchanged. * * - Use when you want to apply the same transformation to a subset of * properties. * - Does not mutate the input; returns a fresh object. * * **Example** (Wrapping only selected values in arrays) * * ```ts * import { pipe, Struct } from "effect" * * interface AsArray extends Struct.Lambda { * (self: A): Array * readonly "~lambda.out": Array * } * * const asArray = Struct.lambda((a) => [a]) * const result = pipe( * { x: 1, y: 2, z: 3 }, * Struct.mapPick(["x", "z"], asArray) * ) * console.log(result) // { x: [1], y: 2, z: [3] } * ``` * * @see {@link map} – apply a lambda to all keys * @see {@link mapOmit} – apply a lambda to all keys except selected ones * * @category Mapping * @since 4.0.0 */ , L extends Lambda>(keys: Keys, lambda: L): (self: S) => { [K in keyof S]: K extends Keys[number] ? Apply : S[K]; }; /** * Applies a {@link Lambda} transformation only to the specified keys; all * other keys are copied unchanged. * * - Use when you want to apply the same transformation to a subset of * properties. * - Does not mutate the input; returns a fresh object. * * **Example** (Wrapping only selected values in arrays) * * ```ts * import { pipe, Struct } from "effect" * * interface AsArray extends Struct.Lambda { * (self: A): Array * readonly "~lambda.out": Array * } * * const asArray = Struct.lambda((a) => [a]) * const result = pipe( * { x: 1, y: 2, z: 3 }, * Struct.mapPick(["x", "z"], asArray) * ) * console.log(result) // { x: [1], y: 2, z: [3] } * ``` * * @see {@link map} – apply a lambda to all keys * @see {@link mapOmit} – apply a lambda to all keys except selected ones * * @category Mapping * @since 4.0.0 */ , L extends Lambda>(self: S, keys: Keys, lambda: L): { [K in keyof S]: K extends Keys[number] ? Apply : S[K]; }; }; /** * Applies a {@link Lambda} transformation to all keys except the specified * ones; the excluded keys are copied unchanged. * * - Use when most keys should be transformed but a few should be preserved. * - Does not mutate the input; returns a fresh object. * * **Example** (Wrapping all values except one in arrays) * * ```ts * import { pipe, Struct } from "effect" * * interface AsArray extends Struct.Lambda { * (self: A): Array * readonly "~lambda.out": Array * } * * const asArray = Struct.lambda((a) => [a]) * const result = pipe( * { x: 1, y: 2, z: 3 }, * Struct.mapOmit(["y"], asArray) * ) * console.log(result) // { x: [1], y: 2, z: [3] } * ``` * * @see {@link map} – apply a lambda to all keys * @see {@link mapPick} – apply a lambda only to selected keys * * @category Mapping * @since 4.0.0 */ export declare const mapOmit: { /** * Applies a {@link Lambda} transformation to all keys except the specified * ones; the excluded keys are copied unchanged. * * - Use when most keys should be transformed but a few should be preserved. * - Does not mutate the input; returns a fresh object. * * **Example** (Wrapping all values except one in arrays) * * ```ts * import { pipe, Struct } from "effect" * * interface AsArray extends Struct.Lambda { * (self: A): Array * readonly "~lambda.out": Array * } * * const asArray = Struct.lambda((a) => [a]) * const result = pipe( * { x: 1, y: 2, z: 3 }, * Struct.mapOmit(["y"], asArray) * ) * console.log(result) // { x: [1], y: 2, z: [3] } * ``` * * @see {@link map} – apply a lambda to all keys * @see {@link mapPick} – apply a lambda only to selected keys * * @category Mapping * @since 4.0.0 */ , L extends Lambda>(keys: Keys, lambda: L): (self: S) => { [K in keyof S]: K extends Keys[number] ? S[K] : Apply; }; /** * Applies a {@link Lambda} transformation to all keys except the specified * ones; the excluded keys are copied unchanged. * * - Use when most keys should be transformed but a few should be preserved. * - Does not mutate the input; returns a fresh object. * * **Example** (Wrapping all values except one in arrays) * * ```ts * import { pipe, Struct } from "effect" * * interface AsArray extends Struct.Lambda { * (self: A): Array * readonly "~lambda.out": Array * } * * const asArray = Struct.lambda((a) => [a]) * const result = pipe( * { x: 1, y: 2, z: 3 }, * Struct.mapOmit(["y"], asArray) * ) * console.log(result) // { x: [1], y: 2, z: [3] } * ``` * * @see {@link map} – apply a lambda to all keys * @see {@link mapPick} – apply a lambda only to selected keys * * @category Mapping * @since 4.0.0 */ , L extends Lambda>(self: S, keys: Keys, lambda: L): { [K in keyof S]: K extends Keys[number] ? S[K] : Apply; }; }; /** * Creates a `Combiner` for a struct shape by providing a `Combiner` for each * property. When two structs are combined, each property is merged using its * corresponding combiner. * * - Use when you need to merge two structs of the same shape (e.g., summing * counters, concatenating strings). * - Pass `omitKeyWhen` to drop properties whose merged value matches a * predicate (e.g., omit zero counters). * - Does not mutate the inputs; returns a fresh object. * * **Example** (Combining struct properties) * * ```ts * import { Number, String, Struct } from "effect" * * const C = Struct.makeCombiner<{ readonly n: number; readonly s: string }>({ * n: Number.ReducerSum, * s: String.ReducerConcat * }) * * const result = C.combine({ n: 1, s: "hello" }, { n: 2, s: " world" }) * console.log(result) // { n: 3, s: "hello world" } * ``` * * @see {@link makeReducer} – like `makeCombiner` but with an initial value * * @since 4.0.0 */ export declare function makeCombiner(combiners: { readonly [K in keyof A]: Combiner.Combiner; }, options?: { readonly omitKeyWhen?: ((a: A[keyof A]) => boolean) | undefined; }): Combiner.Combiner; /** * Creates a `Reducer` for a struct shape by providing a `Reducer` for each * property. The initial value is derived from each property's * `Reducer.initialValue`. When reducing a collection of structs, each property * is combined independently. * * - Use to fold a collection of structs into a single summary struct. * - Pass `omitKeyWhen` to drop properties whose reduced value matches a * predicate. * - Does not mutate the inputs; returns a fresh object. * * **Example** (Reducing a collection of structs) * * ```ts * import { Number, String, Struct } from "effect" * * const R = Struct.makeReducer<{ readonly n: number; readonly s: string }>({ * n: Number.ReducerSum, * s: String.ReducerConcat * }) * * const result = R.combineAll([ * { n: 1, s: "a" }, * { n: 2, s: "b" }, * { n: 3, s: "c" } * ]) * console.log(result) // { n: 6, s: "abc" } * ``` * * @see {@link makeCombiner} – like `makeReducer` but without an initial value * * @since 4.0.0 */ export declare function makeReducer(reducers: { readonly [K in keyof A]: Reducer.Reducer; }, options?: { readonly omitKeyWhen?: ((a: A[keyof A]) => boolean) | undefined; }): Reducer.Reducer; /** * Creates a record with the given keys and value. * * **Example** (Creating a record) * * ```ts * import { Struct } from "effect" * * const record = Struct.Record(["a", "b"], "value") * console.log(record) // { a: "value", b: "value" } * ``` * * @category Constructors * @since 4.0.0 */ export declare function Record, Value>(keys: Keys, value: Value): Record; export {}; //# sourceMappingURL=Struct.d.ts.map