Repository: Effect-TS/effect (TypeScript)

Issue:
Arbitrary.make called on Schema.Class does not take props annotations into account
To reproduce:

```
import { Arbitrary, FastCheck, Schema } from 'effect'

const someSchema = Schema.Struct({
  bigInt: Schema.BigInt.annotations({
    arbitrary: () => (fc) => fc.bigInt({ min: BigInt(0), max: BigInt(1000) }),
  }),
});

it('Arbitrary works on schema struct', () => {
  for (let i = 0; i < 10; i++) {
    console.log(FastCheck.sample(Arbitrary.make(someSchema), 1)[0]);
  }
});

class someClass extends Schema.Class<someClass>('someClass')({
  bigInt: Schema.BigInt.annotations({
    arbitrary: () => (fc) => fc.bigInt({ min: BigInt(0), max: BigInt(1000) }),
  }),
}) {}

it('Arbitrary does not work on schema class', () => {
  for (let i = 0; i < 10; i++) {
    console.log(FastCheck.sample(Arbitrary.make(someClass), 1)[0]);
  }
});
```


Discussion:

Patch:
diff --git a/.changeset/lemon-peas-try.md b/.changeset/lemon-peas-try.md
new file mode 100644
index 00000000000..5881b342a4d
--- /dev/null
+++ b/.changeset/lemon-peas-try.md
@@ -0,0 +1,58 @@
+---
+"effect": patch
+---
+
+Arbitrary: `make` called on `Schema.Class` now respects property annotations, closes #4550.
+
+Previously, when calling `Arbitrary.make` on a `Schema.Class`, property-specific annotations (such as `arbitrary`) were ignored, leading to unexpected values in generated instances.
+
+Before
+
+Even though `a` had an `arbitrary` annotation, the generated values were random:
+
+```ts
+import { Arbitrary, FastCheck, Schema } from "effect"
+
+class Class extends Schema.Class<Class>("Class")({
+  a: Schema.NumberFromString.annotations({
+    arbitrary: () => (fc) => fc.constant(1)
+  })
+}) {}
+
+console.log(FastCheck.sample(Arbitrary.make(Class), 5))
+/*
+Example Output:
+[
+  Class { a: 2.6624670822171524e-44 },
+  Class { a: 3.4028177873105996e+38 },
+  Class { a: 3.402820626847944e+38 },
+  Class { a: 3.783505853677006e-44 },
+  Class { a: 3243685 }
+]
+*/
+```
+
+After
+
+Now, the values respect the `arbitrary` annotation and return the expected constant:
+
+```ts
+import { Arbitrary, FastCheck, Schema } from "effect"
+
+class Class extends Schema.Class<Class>("Class")({
+  a: Schema.NumberFromString.annotations({
+    arbitrary: () => (fc) => fc.constant(1)
+  })
+}) {}
+
+console.log(FastCheck.sample(Arbitrary.make(Class), 5))
+/*
+[
+  Class { a: 1 },
+  Class { a: 1 },
+  Class { a: 1 },
+  Class { a: 1 },
+  Class { a: 1 }
+]
+*/
+```
diff --git a/packages/effect/src/Schema.ts b/packages/effect/src/Schema.ts
index 275caa864d3..0a09a4cd9a5 100644
--- a/packages/effect/src/Schema.ts
+++ b/packages/effect/src/Schema.ts
@@ -8907,7 +8907,7 @@ const makeClass = <Fields extends Struct.Fields>(
       }
 
       const declaration: Schema.Any = declare(
-        [typeSide],
+        [schema],
         {
           decode: () => (input, _, ast) =>
             input instanceof this || fallbackInstanceOf(input)


Test patch:
diff --git a/packages/effect/test/Schema/Arbitrary/Class.test.ts b/packages/effect/test/Schema/Arbitrary/Class.test.ts
index 8daba149fa4..572b5f72d07 100644
--- a/packages/effect/test/Schema/Arbitrary/Class.test.ts
+++ b/packages/effect/test/Schema/Arbitrary/Class.test.ts
@@ -1,8 +1,16 @@
 import { describe, it } from "@effect/vitest"
-import * as S from "effect/Schema"
+import { Arbitrary, FastCheck, Schema as S } from "effect"
 import * as Util from "effect/test/Schema/TestUtils"
 
 describe("Class", () => {
+  it("baseline", () => {
+    class Class extends S.Class<Class>("Class")({
+      a: S.String,
+      b: S.NumberFromString
+    }) {}
+    Util.assertions.arbitrary.validateGeneratedValues(Class)
+  })
+
   it("required property signature", () => {
     class Class extends S.Class<Class>("Class")({
       a: S.Number
@@ -31,11 +39,13 @@ describe("Class", () => {
     Util.assertions.arbitrary.validateGeneratedValues(Class)
   })
 
-  it("baseline", () => {
+  it("transformation property signature with annotation (#4550)", () => {
     class Class extends S.Class<Class>("Class")({
-      a: S.String,
-      b: S.NumberFromString
+      a: S.NumberFromString.annotations({
+        arbitrary: () => (fc) => fc.constant(1)
+      })
     }) {}
-    Util.assertions.arbitrary.validateGeneratedValues(Class)
+    const arb = Arbitrary.make(Class)
+    FastCheck.assert(FastCheck.property(arb, (a) => a.a === 1))
   })
 })