Skip to content
LogoLogo

VIP-14: Effect's modules are in scope without an import

Status: accepted by Will, 2026-10-28.

Decision

const Port = Schema.Number                       // Effect's Schema, no import
try sleep(Duration.seconds(1))
const first = Effect.Array.head(xs)              // Effect's Array module: JavaScript's Array wins the bare name
const o = Option.some(1)                         // Effect's Option: the DOM's Option is platform-specific
  • Every root export of the core effect package (149 in effect 4.1.1, such as Schema, Layer, Stream, Option, Data, Context, Schedule, Duration) is in scope in a .vibe file without an import. Emitted code imports each module it uses from effect/<Module>.

  • This is configurable in tsconfig.json, as VIP-6's globals are.

  • Precedence by default. JavaScript globals that aren't platform-specific, and TypeScript's own globals, keep their meaning. Effect's module of the same name is then reachable as Effect.X, or by import.

    NameBare name meansEffect's module
    Array, String, Number, Boolean, BigInt, Symbol, Function, RegExpJavaScript'sEffect.Array, Effect.String, …
    Record, IterableTypeScript's typesEffect.Record, Effect.Iterable
    Request, Option, Cache, FileSystem, Scheduler, Console (platform-specific)Effect's modulethe bare name
  • Amended 2026-10-29: no Crypto row. effect 4.1.1 has no root Crypto module, so bare Crypto is the DOM's. Sent to Will on Telegram 2026-10-29 11:28 under his standing rule 'assume I accept'; no objection by 12:00.

  • Amended 2026-10-29: names two subpaths export. A namespace name that two subpaths export, or a subpath and the root, is not in scope bare. Using it is a compile error that names every exporter and offers one import per exporter: in 4.1.1, Model, Prompt and Utils. Decided by the agent on 2026-10-29 under Will's rule "when I state a principle, the agent derives the concrete rule and acts; I can override later" (decided detail 55).

History

One minor finding, "unclassified globals", resolved. No other findings.

Prior art

Rust's prelude; Elixir's Kernel; VIP-6.

Will's words

"So like before this should be configurable in the tsconfig.json but by default we should make javascript globals that are not platform specific take president but we should also make them available on Effect.* not just via impport with those changes I accept"

"Yea Typescript globals like Record take president"

  • Amended 2026-11-01: collision qualifiers use the implicit binding. Effect.Array, Effect.String, Effect.Record and other colliding-module qualifiers are intrinsic to the compiler's implicit Effect; they are not exports of effect/Effect. A written binding, imported under any name or declared locally, keeps its TypeScript meaning and shadows the implicit binding. An explicit namespace has no Array member (TS2339); use import { Array as Arr } from "effect". Turning vibe.effectModules off removes the implicit qualifier without changing explicit imports.