Skip to content

Commit 9bfe8a9

Browse files
mikearnaldieffect-bot
authored andcommitted
introduce ReadonlyTag as a Tag that can only be used to read a service from requirements (#5305)
1 parent d2760e9 commit 9bfe8a9

File tree

2 files changed

+64
-3
lines changed

2 files changed

+64
-3
lines changed

.changeset/little-singers-wash.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
---
2+
"effect": minor
3+
---
4+
5+
Introduce ReadonlyTag as the covariant side of a tag, enables:
6+
7+
```ts
8+
import type { Context } from "effect"
9+
import { Effect } from "effect"
10+
11+
export class MyRequirement extends Effect.Service<MyRequirement>()(
12+
"MyRequirement",
13+
{ succeed: () => 42 }
14+
) {}
15+
16+
export class MyUseCase extends Effect.Service<MyUseCase>()("MyUseCase", {
17+
dependencies: [MyRequirement.Default],
18+
effect: Effect.gen(function* () {
19+
const requirement = yield* MyRequirement
20+
return Effect.fn("MyUseCase.execute")(function* () {
21+
return requirement()
22+
})
23+
})
24+
}) {}
25+
26+
export function effectHandler<I, Args extends Array<any>, A, E, R>(
27+
service: Context.ReadonlyTag<I, (...args: Args) => Effect.Effect<A, E, R>>
28+
) {
29+
return Effect.fn("effectHandler")(function* (...args: Args) {
30+
const execute = yield* service
31+
yield* execute(...args)
32+
})
33+
}
34+
35+
export const program = effectHandler(MyUseCase)
36+
```

packages/effect/src/Context.ts

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
*
88
* @since 2.0.0
99
*/
10+
import type * as Effect from "./Effect.js"
1011
import type { Equal } from "./Equal.js"
1112
import type { LazyArg } from "./Function.js"
1213
import type { Inspectable } from "./Inspectable.js"
@@ -16,7 +17,11 @@ import type { Pipeable } from "./Pipeable.js"
1617
import type * as Types from "./Types.js"
1718
import type * as Unify from "./Unify.js"
1819

19-
const TagTypeId: unique symbol = internal.TagTypeId
20+
/**
21+
* @since 2.0.0
22+
* @category symbol
23+
*/
24+
export const TagTypeId: unique symbol = internal.TagTypeId
2025

2126
/**
2227
* @since 2.0.0
@@ -28,7 +33,7 @@ export type TagTypeId = typeof TagTypeId
2833
* @since 3.5.9
2934
* @category models
3035
*/
31-
export interface Tag<in out Id, in out Value> extends Pipeable, Inspectable {
36+
export interface Tag<in out Id, in out Value> extends Pipeable, Inspectable, ReadonlyTag<Id, Value> {
3237
readonly _op: "Tag"
3338
readonly Service: Value
3439
readonly Identifier: Id
@@ -45,7 +50,27 @@ export interface Tag<in out Id, in out Value> extends Pipeable, Inspectable {
4550
[Unify.ignoreSymbol]?: TagUnifyIgnore
4651
}
4752

48-
const ReferenceTypeId: unique symbol = internal.ReferenceTypeId
53+
/**
54+
* @since 3.5.9
55+
* @category models
56+
*/
57+
export interface ReadonlyTag<in out Id, out Value> extends Pipeable, Inspectable, Effect.Effect<Value, never, Id> {
58+
readonly _op: "Tag"
59+
readonly Service: Value
60+
readonly Identifier: Id
61+
readonly [TagTypeId]: {
62+
readonly _Service: Types.Covariant<Value>
63+
readonly _Identifier: Types.Invariant<Id>
64+
}
65+
readonly stack?: string | undefined
66+
readonly key: string
67+
}
68+
69+
/**
70+
* @since 3.11.0
71+
* @category symbol
72+
*/
73+
export const ReferenceTypeId: unique symbol = internal.ReferenceTypeId
4974

5075
/**
5176
* @since 3.11.0

0 commit comments

Comments
 (0)