Skip to content

Commit

Permalink
Implement Effect.Service and allow multiple layers to be provided in …
Browse files Browse the repository at this point in the history
…Effect.provide (#3690)

Co-authored-by: Tim <hello@timsmart.co>
Co-authored-by: Patrick Roza <contact@patrickroza.com>
  • Loading branch information
3 people committed Oct 6, 2024
1 parent 0ba66f2 commit d75140c
Show file tree
Hide file tree
Showing 10 changed files with 763 additions and 95 deletions.
5 changes: 5 additions & 0 deletions .changeset/old-ways-accept.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"effect": minor
---

Support providing an array of layers via Effect.provide and Layer.provide
53 changes: 53 additions & 0 deletions .changeset/twelve-dots-enjoy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
---
"effect": minor
---

Implement Effect.Service as a Tag and Layer with Opaque Type.

Namely the following is now possible:

```ts
class Prefix extends Effect.Service<Prefix>()("Prefix", {
sync: () => ({
prefix: "PRE"
})
}) {}

class Postfix extends Effect.Service<Postfix>()("Postfix", {
sync: () => ({
postfix: "POST"
})
}) {}

const messages: Array<string> = []

class Logger extends Effect.Service<Logger>()("Logger", {
accessors: true,
effect: Effect.gen(function* () {
const { prefix } = yield* Prefix
const { postfix } = yield* Postfix
return {
info: (message: string) =>
Effect.sync(() => {
messages.push(`[${prefix}][${message}][${postfix}]`)
})
}
}),
dependencies: [Prefix.Default, Postfix.Default]
}) {}

describe("Effect", () => {
it.effect("Service correctly wires dependencies", () =>
Effect.gen(function* () {
const { _tag } = yield* Logger
expect(_tag).toEqual("Logger")
yield* Logger.info("Ok")
expect(messages).toEqual(["[PRE][Ok][POST]"])
const { prefix } = yield* Prefix
expect(prefix).toEqual("PRE")
const { postfix } = yield* Postfix
expect(postfix).toEqual("POST")
}).pipe(Effect.provide([Logger.Default, Prefix.Default, Postfix.Default]))
)
})
```
5 changes: 2 additions & 3 deletions packages/effect/src/Context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ export type TagTypeId = typeof TagTypeId
* @category models
*/
export interface Tag<in out Id, in out Value> extends Pipeable, Inspectable {
readonly _tag: "Tag"
readonly _op: "Tag"
readonly Service: Value
readonly Identifier: Id
Expand Down Expand Up @@ -85,13 +84,13 @@ export declare namespace Tag {
/**
* @since 2.0.0
*/
export type Service<T extends Tag<any, any> | TagClassShape<any, any>> = T extends Tag<any, infer A> ? A
export type Service<T extends Tag<any, any> | TagClassShape<any, any>> = T extends Tag<any, any> ? T["Service"]
: T extends TagClassShape<any, infer A> ? A
: never
/**
* @since 2.0.0
*/
export type Identifier<T extends Tag<any, any> | TagClassShape<any, any>> = T extends Tag<infer A, any> ? A
export type Identifier<T extends Tag<any, any> | TagClassShape<any, any>> = T extends Tag<any, any> ? T["Identifier"]
: T extends TagClassShape<any, any> ? T
: never
}
Expand Down
Loading

0 comments on commit d75140c

Please sign in to comment.