diff --git a/.changeset/wise-kiwis-tan.md b/.changeset/wise-kiwis-tan.md new file mode 100644 index 0000000000..e0dd75dca8 --- /dev/null +++ b/.changeset/wise-kiwis-tan.md @@ -0,0 +1,16 @@ +--- +"effect": minor +--- + +The `FiberRef` is now a subtype of `Effect`. This change simplifies handling of deferred values, removing the need for explicit call `FiberRef.get`. + +```typescript +import { Effect, FiberRef } from "effect" + +Effect.gen(function* () { + const fiberRef = yield* FiberRef.make("value") + + const before = yield* FiberRef.get(fiberRef) + const after = yield* fiberRef +}) +``` diff --git a/packages/effect/dtslint/Unify.ts b/packages/effect/dtslint/Unify.ts index 87baa5d34e..175fe08137 100644 --- a/packages/effect/dtslint/Unify.ts +++ b/packages/effect/dtslint/Unify.ts @@ -2,6 +2,7 @@ import type * as Deferred from "effect/Deferred" import type * as Effect from "effect/Effect" import * as Either from "effect/Either" import type * as Exit from "effect/Exit" +import type * as FiberRef from "effect/FiberRef" import type * as Micro from "effect/Micro" import type * as Option from "effect/Option" import type * as RcRef from "effect/RcRef" @@ -72,8 +73,13 @@ export type DeferredUnify = Unify.Unify< | Deferred.Deferred<1, 2> | Deferred.Deferred<"a", "b"> > +// $ExpectType FiberRef<1> | FiberRef<"a"> +export type FiberRefUnify = Unify.Unify< + | FiberRef.FiberRef<1> + | FiberRef.FiberRef<"a"> +> -// $ExpectType 0 | Option | Ref<1> | SynchronizedRef<1> | SubscriptionRef<1> | Deferred<1, 2> | Deferred<"a", "b"> | Ref<"A"> | SynchronizedRef<"A"> | SubscriptionRef<"A"> | Either<1 | "A", 0 | "E"> | Effect<1 | "A", 0 | "E", "R" | "R1"> | RcRef<1 | "A", 0 | "E"> +// $ExpectType 0 | Option | Ref<1> | SynchronizedRef<1> | SubscriptionRef<1> | Deferred<1, 2> | Deferred<"a", "b"> | Ref<"A"> | SynchronizedRef<"A"> | SubscriptionRef<"A"> | FiberRef<12> | FiberRef<"a2"> | Either<1 | "A", 0 | "E"> | Effect<1 | "A", 0 | "E", "R" | "R1"> | RcRef<1 | "A", 0 | "E"> export type AllUnify = Unify.Unify< | Either.Either<1, 0> | Either.Either<"A", "E"> @@ -91,5 +97,7 @@ export type AllUnify = Unify.Unify< | RcRef.RcRef<"A", "E"> | Deferred.Deferred<1, 2> | Deferred.Deferred<"a", "b"> + | FiberRef.FiberRef<12> + | FiberRef.FiberRef<"a2"> | 0 > diff --git a/packages/effect/src/FiberRef.ts b/packages/effect/src/FiberRef.ts index 463858adbc..ae95e146b0 100644 --- a/packages/effect/src/FiberRef.ts +++ b/packages/effect/src/FiberRef.ts @@ -18,7 +18,6 @@ import type * as LogLevel from "./LogLevel.js" import type * as LogSpan from "./LogSpan.js" import type * as MetricLabel from "./MetricLabel.js" import type * as Option from "./Option.js" -import type { Pipeable } from "./Pipeable.js" import type * as Request from "./Request.js" import type * as RuntimeFlags from "./RuntimeFlags.js" import * as Scheduler from "./Scheduler.js" @@ -26,6 +25,7 @@ import type * as Scope from "./Scope.js" import type * as Supervisor from "./Supervisor.js" import type * as Tracer from "./Tracer.js" import type * as Types from "./Types.js" +import type * as Unify from "./Unify.js" /** * @since 2.0.0 @@ -43,7 +43,7 @@ export type FiberRefTypeId = typeof FiberRefTypeId * @since 2.0.0 * @category model */ -export interface FiberRef extends Variance, Pipeable { +export interface FiberRef extends Effect.Effect, Variance { /** @internal */ readonly initial: A /** @internal */ @@ -56,6 +56,25 @@ export interface FiberRef extends Variance, Pipeable { readonly fork: unknown /** @internal */ join(oldValue: A, newValue: A): A + readonly [Unify.typeSymbol]?: unknown + readonly [Unify.unifySymbol]?: FiberRefUnify + readonly [Unify.ignoreSymbol]?: FiberRefUnifyIgnore +} + +/** + * @category models + * @since 3.8.0 + */ +export interface FiberRefUnify extends Effect.EffectUnify { + FiberRef?: () => Extract> +} + +/** + * @category models + * @since 3.8.0 + */ +export interface FiberRefUnifyIgnore extends Effect.EffectUnifyIgnore { + Effect?: true } /** diff --git a/packages/effect/src/internal/core.ts b/packages/effect/src/internal/core.ts index 8216dfcd93..4b3350fba3 100644 --- a/packages/effect/src/internal/core.ts +++ b/packages/effect/src/internal/core.ts @@ -1955,18 +1955,22 @@ export const fiberRefUnsafeMakePatch = ( readonly fork: Patch readonly join?: ((oldV: Value, newV: Value) => Value) | undefined } -): FiberRef.FiberRef => ({ - [FiberRefTypeId]: fiberRefVariance, - initial, - diff: (oldValue, newValue) => options.differ.diff(oldValue, newValue), - combine: (first, second) => options.differ.combine(first as Patch, second as Patch), - patch: (patch) => (oldValue) => options.differ.patch(patch as Patch, oldValue), - fork: options.fork, - join: options.join ?? ((_, n) => n), - pipe() { - return pipeArguments(this, arguments) +): FiberRef.FiberRef => { + const _fiberRef = { + ...CommitPrototype, + [FiberRefTypeId]: fiberRefVariance, + initial, + commit() { + return fiberRefGet(this) + }, + diff: (oldValue: Value, newValue: Value) => options.differ.diff(oldValue, newValue), + combine: (first: Patch, second: Patch) => options.differ.combine(first, second), + patch: (patch: Patch) => (oldValue: Value) => options.differ.patch(patch, oldValue), + fork: options.fork, + join: options.join ?? ((_, n) => n) } -}) + return _fiberRef +} /** @internal */ export const fiberRefUnsafeMakeRuntimeFlags = ( diff --git a/packages/effect/test/FiberRef.test.ts b/packages/effect/test/FiberRef.test.ts index 9f8e928d13..41534de743 100644 --- a/packages/effect/test/FiberRef.test.ts +++ b/packages/effect/test/FiberRef.test.ts @@ -361,4 +361,10 @@ describe("FiberRef", () => { const result = yield* $(Deferred.await(deferred)) assert.isTrue(result) })) + it.scoped("is subtype of Effect", () => + Effect.gen(function*() { + const fiberRef = yield* FiberRef.make(initial) + const result = yield* fiberRef + assert.strictEqual(result, initial) + })) })