or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

concurrency-fibers.mdcontext-services.mddata-structures.mdeffect-core.mderror-observability.mdfunction-utilities.mdindex.mdlayer-system.mdschema-validation.mdstreaming.md
tile.json

layer-system.mddocs/

Layer System

Modular service composition and resource management system for building applications with managed dependencies, automatic resource cleanup, and hierarchical service construction.

Capabilities

Layer Construction

interface Layer<out ROut, out E = never, out RIn = never> extends Pipeable {}

declare namespace Layer {
  /**
   * Creates a layer that provides a service
   */
  function succeed<T>(tag: Tag<T, T>, resource: T): Layer<T>;
  
  /**
   * Creates a layer from an Effect
   */
  function effect<T, E, R>(tag: Tag<T, T>, effect: Effect<T, E, R>): Layer<T, E, R>;
  
  /**
   * Creates a scoped layer with automatic cleanup
   */
  function scoped<T, E, R>(tag: Tag<T, T>, effect: Effect<T, E, R>): Layer<T, E, Exclude<R, Scope>>;
  
  /**
   * Provides a layer to an Effect
   */
  function provide<RIn, E, ROut>(layer: Layer<RIn, E>): <A, E1, ROut1>(self: Effect<A, E1, RIn | ROut1>) => Effect<A, E | E1, ROut | ROut1>;
  
  /**
   * Merges two layers
   */
  function merge<R1, E1, R2, E2>(that: Layer<R2, E2>): (self: Layer<R1, E1>) => Layer<R1 | R2, E1 | E2>;
}

Usage Examples:

import { Layer, Context, Effect } from "effect";

// Service definitions
interface Database {
  query(sql: string): Effect<unknown[]>;
}

interface Logger {
  log(message: string): Effect<void>;
}

const Database = Context.GenericTag<Database>("Database");
const Logger = Context.GenericTag<Logger>("Logger");

// Layer implementations
const DatabaseLive = Layer.effect(
  Database,
  Effect.gen(function* () {
    yield* Effect.log("Connecting to database");
    return {
      query: (sql: string) => Effect.succeed([{ result: `Query: ${sql}` }])
    };
  })
);

const LoggerLive = Layer.succeed(Logger, {
  log: (message) => Effect.sync(() => console.log(message))
});

// Combined layer
const AppLayer = Layer.merge(DatabaseLive)(LoggerLive);

// Usage
const program = Effect.gen(function* () {
  const db = yield* Database;
  const logger = yield* Logger;
  
  yield* logger.log("Starting application");
  const results = yield* db.query("SELECT * FROM users");
  yield* logger.log(`Found ${results.length} results`);
  
  return results;
});

const runnable = pipe(program, Layer.provide(AppLayer));

Types

interface Scope {
  readonly close: (exit: Exit<unknown, unknown>) => Effect<void>;
}