Hyperlinkv0.8.0-beta.28

Layer

Layer.provideMergeconsteffect/Layer.ts:1490
<RIn, E, ROut>(that: Layer<ROut, E, RIn>): <RIn2, E2, ROut2>(
  self: Layer<ROut2, E2, RIn2>
) => Layer<ROut | ROut2, E | E2, RIn | Exclude<RIn2, ROut>>
<const Layers extends [Any, ...Array<Any>]>(that: Layers): <A, E, R>(
  self: Layer<A, E, R>
) => Layer<
  A | Success<Layers[number]>,
  E | Error<Layers[number]>,
  Services<Layers[number]> | Exclude<R, Success<Layers[number]>>
>
<RIn2, E2, ROut2, RIn, E, ROut>(
  self: Layer<ROut2, E2, RIn2>,
  that: Layer<ROut, E, RIn>
): Layer<ROut | ROut2, E | E2, RIn | Exclude<RIn2, ROut>>
<A, E, R, const Layers extends [Any, ...Array<Any>]>(
  self: Layer<A, E, R>,
  that: Layers
): Layer<
  A | Success<Layers[number]>,
  E | Error<Layers[number]>,
  Services<Layers[number]> | Exclude<R, Success<Layers[number]>>
>

Feeds the output services of the dependency layer into the requirements of this layer, returning a layer that provides both sets of services.

When to use

Use when you need to compose Layers while keeping both the constructed service and the dependency used to build it available.

Details

Prefer provide when the dependency should stay private.

Example (Providing dependencies while retaining services)

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

class Database extends Context.Service<Database, {
  readonly query: (sql: string) => Effect.Effect<string>
}>()("Database") {}

class Logger extends Context.Service<Logger, {
  readonly log: (msg: string) => Effect.Effect<void>
}>()("Logger") {}

class UserService extends Context.Service<UserService, {
  readonly getUser: (id: string) => Effect.Effect<{
    id: string
    name: string
  }>
}>()("UserService") {}

// Create dependency layers
const databaseLayer = Layer.succeed(Database, {
  query: Effect.fn("Database.query")((sql: string) => Effect.succeed(`DB: ${sql}`))
})

const loggerLayer = Layer.succeed(Logger, {
  log: Effect.fn("Logger.log")((msg: string) => Effect.sync(() => console.log(`[LOG] ${msg}`)))
})

// UserService depends on Database and Logger
const userServiceLayer = Layer.effect(UserService, Effect.gen(function*() {
  const database = yield* Database
  const logger = yield* Logger

  return {
    getUser: Effect.fn("UserService.getUser")(function*(id: string) {
        yield* logger.log(`Looking up user ${id}`)
        const result = yield* database.query(
          `SELECT * FROM users WHERE id = ${id}`
        )
        return { id, name: result }
      })
  }
}))

// Provide dependencies and merge all services together
const allServicesLayer = userServiceLayer.pipe(
  Layer.provideMerge(Layer.mergeAll(databaseLayer, loggerLayer))
)

// Now the resulting layer provides UserService, Database, AND Logger
const program = Effect.gen(function*() {
  const userService = yield* UserService
  const logger = yield* Logger // Still available!
  const database = yield* Database // Still available!

  const user = yield* userService.getUser("123")
  yield* logger.log(`Found user: ${user.name}`)

  return user
}).pipe(
  Effect.provide(allServicesLayer)
)
providing servicesprovide
Source effect/Layer.ts:149036 lines
export const provideMerge: {
  <RIn, E, ROut>(
    that: Layer<ROut, E, RIn>
  ): <RIn2, E2, ROut2>(self: Layer<ROut2, E2, RIn2>) => Layer<ROut | ROut2, E | E2, RIn | Exclude<RIn2, ROut>>
  <const Layers extends [Any, ...Array<Any>]>(
    that: Layers
  ): <A, E, R>(
    self: Layer<A, E, R>
  ) => Layer<
    A | Success<Layers[number]>,
    E | Error<Layers[number]>,
    | Services<Layers[number]>
    | Exclude<R, Success<Layers[number]>>
  >
  <RIn2, E2, ROut2, RIn, E, ROut>(
    self: Layer<ROut2, E2, RIn2>,
    that: Layer<ROut, E, RIn>
  ): Layer<ROut | ROut2, E | E2, RIn | Exclude<RIn2, ROut>>
  <A, E, R, const Layers extends [Any, ...Array<Any>]>(
    self: Layer<A, E, R>,
    that: Layers
  ): Layer<
    A | Success<Layers[number]>,
    E | Error<Layers[number]>,
    | Services<Layers[number]>
    | Exclude<R, Success<Layers[number]>>
  >
} = dual(2, (
  self: Layer<any, any, any>,
  that: Layer<any, any, any> | ReadonlyArray<Layer<any, any, any>>
) =>
  provideWith(
    self,
    that,
    (self, that) => Context.merge(that, self)
  ))
Referenced by 6 symbols