diff --git a/packages/effect/dtslint/Effect.tst.ts b/packages/effect/dtslint/Effect.tst.ts index 4c9f794c66c..eadac55643f 100644 --- a/packages/effect/dtslint/Effect.tst.ts +++ b/packages/effect/dtslint/Effect.tst.ts @@ -1,5 +1,5 @@ import type { Either, Types } from "effect" -import { Array as Arr, Context, Effect, hole, Option, pipe, Predicate, Schedule } from "effect" +import { Array as Arr, Context, Data, Effect, hole, Option, pipe, Predicate, Schedule } from "effect" import type { NonEmptyArray, NonEmptyReadonlyArray } from "effect/Array" import type { Cause, NoSuchElementException, UnknownException } from "effect/Cause" import type { Exit } from "effect/Exit" @@ -14,6 +14,10 @@ class TestError2 { class TestService extends Context.Tag("TestService")() {} +class RateLimitError extends Data.TaggedError("RateLimitError")<{ + readonly retryAfter: number +}> {} + declare const string: Effect.Effect declare const number: Effect.Effect declare const boolean: Effect.Effect @@ -1548,4 +1552,107 @@ describe("Effect", () => { Effect.Effect >() }) + + describe("Effect.fn", () => { + it("with a span, generator", () => { + const fn = Effect.fn("span")(function*() { + return yield* Effect.fail("bye") + }) + expect(fn).type.toBe<() => Effect.Effect>() + }) + + it("with a span, generator with yieldable", () => { + const fn = Effect.fn("span")(function*() { + return yield* new RateLimitError({ retryAfter: 1 }) + }) + expect(fn).type.toBe<() => Effect.Effect>() + }) + + it("with a span, generator and pipe arguments", () => { + const fn = Effect.fn("span")( + function*() { + return yield* Effect.succeed("hello") + }, + Effect.map((x) => { + expect(x).type.toBe() + return x.length + }) + ) + expect(fn).type.toBe<() => Effect.Effect>() + }) + + it("without a span, generator", () => { + const fn = Effect.fn(function*() { + return yield* Effect.fail("bye") + }) + expect(fn).type.toBe<() => Effect.Effect>() + }) + + it("without a span, generator with yieldable", () => { + const fn = Effect.fn(function*() { + return yield* new RateLimitError({ retryAfter: 1 }) + }) + expect(fn).type.toBe<() => Effect.Effect>() + }) + + it("without a span, generator and pipe arguments", () => { + const fn = Effect.fn( + function*() { + return yield* Effect.succeed("hello") + }, + Effect.map((x) => { + expect(x).type.toBe() + return x.length + }) + ) + expect(fn).type.toBe<() => Effect.Effect>() + }) + + it("with a span, function", () => { + const fn = Effect.fn("span")(function() { + return Effect.fail("bye") + }) + expect(fn).type.toBe<() => Effect.Effect>() + }) + + it("with a span, function and pipe arguments", () => { + const fn = Effect.fn("span")( + function() { + return Effect.succeed("hello") + }, + Effect.map((x) => { + expect(x).type.toBe() + return x.length + }) + ) + expect(fn).type.toBe<() => Effect.Effect>() + }) + + it("without a span, function", () => { + const fn = Effect.fn(function() { + return Effect.fail("bye") + }) + expect(fn).type.toBe<() => Effect.Effect>() + }) + + it("without a span, function and pipe arguments", () => { + const fn = Effect.fn( + function() { + return Effect.succeed("hello") + }, + Effect.map((x) => { + expect(x).type.toBe() + return x.length + }) + ) + expect(fn).type.toBe<() => Effect.Effect>() + }) + + it("should not unwrap nested effects", () => { + const fn = Effect.fn(function() { + return Effect.succeed(Effect.succeed(1)) + }) + expect(fn).type.toBe<() => Effect.Effect, never, never>>() + }) + }) })