Skip to content

env EnvLike

Eugene Lazutkin edited this page Jul 13, 2026 · 3 revisions

EnvLike is the method contract that every environment implementation must satisfy. It exists in TypeScript typings only — at runtime the contract is implicit (duck-typed). Both Env (proto-chain) and EnvMap (Map-stack) declare implements EnvLike in their TypeScript declarations and are fully interchangeable as a result.

EnvLike is defined in env-shared.d.ts and can be imported from either entry:

import type {EnvLike} from 'deep6/env.js';
// or equivalently:
import type {EnvLike} from 'deep6/env-map.js';

When to use

Most callers never need EnvLike directly — just pass new Env() or new EnvMap() to unify() and the type system handles the rest.

EnvLike is useful when:

  • Writing custom Unifier subclasses that should accept any conforming environment, not just Env.
  • Writing helpers around unify() that want to abstract over the implementation choice.
  • Implementing a third environment class — declare it implements EnvLike and TypeScript will check that every method is present with the right signature.

Interface

export interface EnvLike {
  depth: number;
  options: Record<string, unknown>;

  push(): void;
  pop(): void;
  revert(depth: number): void;
  bindVar(name1: string | symbol, name2: string | symbol): void;
  bindVal(name: string | symbol, val: unknown): void;
  isBound(name: string | symbol): boolean;
  isAlias(name1: string | symbol, name2: string | symbol): boolean;
  get(name: string | symbol): unknown;
  getAllValues(): Array<{name: string | symbol; value: unknown}>;
}

The two public properties:

  • depth — the current generation number; starts at 0.
  • options — behavioural flags read by unify() (openObjects, openArrays, openMaps, openSets, circular, loose, ignoreFunctions, signedZero, symbols).

Internal storage is intentionally absent from the contract — implementations are free to choose. Env keeps two parallel null-prototype objects; EnvMap keeps Map stacks. Callers should never touch implementation-specific fields.

The methods are described in detail on the Env page; the semantic behaviour is identical across implementations.

Custom implementations

A custom environment is any class with the methods above. Pass an instance as the third argument to unify() and the runtime accepts it — unify() checks for the isBound method to distinguish an environment from an options bag. Example skeleton:

import type {EnvLike} from 'deep6/env.js';

class MyEnv implements EnvLike {
  depth = 0;
  options = {};
  push() {
    /* ... */
  }
  pop() {
    /* ... */
  }
  revert(depth: number) {
    /* ... */
  }
  bindVar(n1: string | symbol, n2: string | symbol) {
    /* ... */
  }
  bindVal(name: string | symbol, val: unknown) {
    /* ... */
  }
  isBound(name: string | symbol) {
    /* ... */ return false;
  }
  isAlias(n1: string | symbol, n2: string | symbol) {
    /* ... */ return false;
  }
  get(name: string | symbol) {
    /* ... */ return undefined;
  }
  getAllValues() {
    return [];
  }
}

See also

  • Env — the proto-chain sibling implementation; methods documented here.
  • EnvMap — the Map-stack alternative implementation.
  • unify() — accepts any EnvLike instance via duck-typed dispatch.

Clone this wiki locally