diff --git a/packages/effect/src/Data.ts b/packages/effect/src/Data.ts index ccc1f7d442..7ec8d15850 100644 --- a/packages/effect/src/Data.ts +++ b/packages/effect/src/Data.ts @@ -451,3 +451,31 @@ export const TaggedError = (tag: Tag): new Args[K] }, Out extends object>( + newable: new(args: Args) => Out, + defaults: Defaults +) => new( + args: Omit & { [K in keyof Args as K extends keyof Defaults ? K : never]?: Args[K] } +) => Out = ( + newable, + defaults +) => { + return class extends (newable as any) { + constructor(args: any) { + super({ + ...args, + ...Object.entries(defaults).reduce((acc, [cur, v]) => { + if (!(cur in args)) { + acc[cur] = (v as any)() + } + return acc + }, {} as Record) + }) + } + } as any +} diff --git a/packages/effect/test/Effect/error.test.ts b/packages/effect/test/Effect/error.test.ts index 6d888f2858..d7185bb0ba 100644 --- a/packages/effect/test/Effect/error.test.ts +++ b/packages/effect/test/Effect/error.test.ts @@ -89,4 +89,14 @@ describe("Effect", () => { class MessageError extends Data.TaggedError("MessageError")<{}> {} assert.deepStrictEqual(new MessageError().toJSON(), { _tag: "MessageError" }) }) + + it.it("withDefaults", () => { + class TestError extends Data.addDefaults( + Data.TaggedError("TestError")<{ a: string; b: number }>, + { b: () => 1 } + ) {} + + assert.deepStrictEqual(new TestError({ a: "hello" }).toJSON(), { _tag: "TestError", a: "hello", b: 1 }) + assert.deepStrictEqual(new TestError({ a: "hello", b: 2 }).toJSON(), { _tag: "TestError", a: "hello", b: 2 }) + }) })