Skip to content

Commit 1bf9f31

Browse files
authoredMar 6, 2024··
Make sure Effect.Tag works with primitives (#2257)
1 parent e466afe commit 1bf9f31

File tree

3 files changed

+68
-12
lines changed

3 files changed

+68
-12
lines changed
 

‎.changeset/good-dots-sleep.md

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
---
2+
"effect": patch
3+
---
4+
5+
Make sure Effect.Tag works on primitives.
6+
7+
This change allows the following to work just fine:
8+
9+
```ts
10+
import { Effect, Layer } from "effect";
11+
12+
class DateTag extends Effect.Tag("DateTag")<DateTag, Date>() {
13+
static date = new Date(1970, 1, 1);
14+
static Live = Layer.succeed(this, this.date);
15+
}
16+
17+
class MapTag extends Effect.Tag("MapTag")<MapTag, Map<string, string>>() {
18+
static Live = Layer.effect(
19+
this,
20+
Effect.sync(() => new Map())
21+
);
22+
}
23+
24+
class NumberTag extends Effect.Tag("NumberTag")<NumberTag, number>() {
25+
static Live = Layer.succeed(this, 100);
26+
}
27+
```

‎packages/effect/src/Effect.ts

+12-12
Original file line numberDiff line numberDiff line change
@@ -5245,18 +5245,18 @@ export const optionFromOptional: <A, E, R>(
52455245
*/
52465246
export const Tag: <const Id extends string>(id: Id) => <Self, Type>() =>
52475247
& Context.TagClass<Self, Id, Type>
5248-
& { _Type: Type }
5249-
& {
5250-
[
5251-
k in keyof Type as Type[k] extends ((...args: [...infer Args]) => infer Ret) ?
5252-
((...args: Readonly<Args>) => Ret) extends Type[k] ? k : never
5253-
: k
5254-
]: Type[k] extends (...args: [...infer Args]) => Effect<infer A, infer E, infer R> ?
5255-
(...args: Readonly<Args>) => Effect<A, E, Self | R>
5256-
: Type[k] extends (...args: [...infer Args]) => infer A ? (...args: Readonly<Args>) => Effect<A, never, Self>
5257-
: Type[k] extends Effect<infer A, infer E, infer R> ? Effect<A, E, Self | R>
5258-
: Effect<Type[k], never, Self>
5259-
}
5248+
& (Type extends Record<PropertyKey, any> ? {
5249+
[
5250+
k in keyof Type as Type[k] extends ((...args: [...infer Args]) => infer Ret) ?
5251+
((...args: Readonly<Args>) => Ret) extends Type[k] ? k : never
5252+
: k
5253+
]: Type[k] extends (...args: [...infer Args]) => Effect<infer A, infer E, infer R> ?
5254+
(...args: Readonly<Args>) => Effect<A, E, Self | R>
5255+
: Type[k] extends (...args: [...infer Args]) => infer A ? (...args: Readonly<Args>) => Effect<A, never, Self>
5256+
: Type[k] extends Effect<infer A, infer E, infer R> ? Effect<A, E, Self | R>
5257+
: Effect<Type[k], never, Self>
5258+
} :
5259+
{})
52605260
& {
52615261
use: <X>(
52625262
body: (_: Type) => X

‎packages/effect/test/Effect/environment.test.ts

+29
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import * as it from "effect-test/utils/extend"
22
import * as Context from "effect/Context"
33
import * as Effect from "effect/Effect"
44
import { pipe } from "effect/Function"
5+
import * as Layer from "effect/Layer"
56
import { assert, describe, expect } from "vitest"
67

78
interface NumberService {
@@ -30,6 +31,19 @@ class DemoTag extends Effect.Tag("DemoTag")<DemoTag, {
3031
}>() {
3132
}
3233

34+
class DateTag extends Effect.Tag("DateTag")<DateTag, Date>() {
35+
static date = new Date(1970, 1, 1)
36+
static Live = Layer.succeed(this, this.date)
37+
}
38+
39+
class MapTag extends Effect.Tag("MapTag")<MapTag, Map<string, string>>() {
40+
static Live = Layer.effect(this, Effect.sync(() => new Map()))
41+
}
42+
43+
class NumberTag extends Effect.Tag("NumberTag")<NumberTag, number>() {
44+
static Live = Layer.succeed(this, 100)
45+
}
46+
3347
describe("Effect", () => {
3448
it.effect("effect tag", () =>
3549
Effect.gen(function*($) {
@@ -51,6 +65,21 @@ describe("Effect", () => {
5165
fn: (...args) => Array.from(args),
5266
fnGen: (s) => [s]
5367
})))
68+
it.effect("effect tag with primitives", () =>
69+
Effect.gen(function*($) {
70+
expect(yield* $(DateTag.getTime())).toEqual(DateTag.date.getTime())
71+
expect(yield* $(NumberTag)).toEqual(100)
72+
expect(Array.from(yield* $(MapTag.keys()))).toEqual([])
73+
yield* $(MapTag.set("foo", "bar"))
74+
expect(Array.from(yield* $(MapTag.keys()))).toEqual(["foo"])
75+
expect(yield* $(MapTag.get("foo"))).toEqual("bar")
76+
}).pipe(
77+
Effect.provide(Layer.mergeAll(
78+
DateTag.Live,
79+
NumberTag.Live,
80+
MapTag.Live
81+
))
82+
))
5483
it.effect("class tag", () =>
5584
Effect.gen(function*($) {
5685
yield* $(

0 commit comments

Comments
 (0)
Please sign in to comment.