Skip to content

Commit 6d2a942

Browse files
authored
Optimize Schema.Class decoding (#6733)
1 parent 7bde6cc commit 6d2a942

3 files changed

Lines changed: 56 additions & 1 deletion

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"effect": patch
3+
---
4+
5+
Avoid validating `Schema.Class` fields twice when decoding.

packages/effect/src/Schema.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14145,7 +14145,14 @@ function makeClass<
1414514145

1414614146
function getClassTransformation(self: new(...args: ReadonlyArray<any>) => any) {
1414714147
return new SchemaTransformation.Transformation<any, any, never, never>(
14148-
SchemaGetter.transform((input) => new self(input)),
14148+
SchemaGetter.transform((input) =>
14149+
new self(input, {
14150+
"~payload": {
14151+
token: payloadToken,
14152+
value: input
14153+
}
14154+
})
14155+
),
1414914156
SchemaGetter.passthrough()
1415014157
)
1415114158
}

packages/effect/test/schema/Schema.test.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6433,6 +6433,22 @@ Expected a value between -2147483648 and 2147483647, got 9007199254740992`
64336433
deepStrictEqual(Effect.runSync(A.makeEffect()), new A())
64346434
})
64356435

6436+
it("decoding validates the class struct once", () => {
6437+
let checks = 0
6438+
const schema = Schema.Struct({
6439+
a: Schema.String
6440+
}).check(Schema.makeFilter(() => {
6441+
checks++
6442+
return true
6443+
}))
6444+
class A extends Schema.Class<A>("A")(schema) {}
6445+
6446+
const instance = Schema.decodeUnknownSync(A)({ a: "a" })
6447+
6448+
assertTrue(instance instanceof A)
6449+
strictEqual(checks, 1)
6450+
})
6451+
64366452
it("suspend before initialization", async () => {
64376453
const schema = Schema.suspend(() => string)
64386454
class A extends Schema.Class<A>("A")(Schema.Struct({ a: schema })) {}
@@ -6752,6 +6768,33 @@ Expected a value between -2147483648 and 2147483647, got 9007199254740992`
67526768
await decoding.succeed({ a: "a", b: 2 }, new B({ a: "a", b: 2 }))
67536769
})
67546770

6771+
it("decoding validates the extended struct once", () => {
6772+
let baseChecks = 0
6773+
let extensionChecks = 0
6774+
class A extends Schema.Class<A>("A")(
6775+
Schema.Struct({
6776+
a: Schema.String
6777+
}).check(Schema.makeFilter(() => {
6778+
baseChecks++
6779+
return true
6780+
}))
6781+
) {}
6782+
class B extends A.extend<B>("B")(
6783+
Schema.Struct({
6784+
b: Schema.Number
6785+
}).check(Schema.makeFilter(() => {
6786+
extensionChecks++
6787+
return true
6788+
}))
6789+
) {}
6790+
6791+
const instance = Schema.decodeUnknownSync(B)({ a: "a", b: 1 })
6792+
6793+
assertTrue(instance instanceof B)
6794+
strictEqual(baseChecks, 1)
6795+
strictEqual(extensionChecks, 1)
6796+
})
6797+
67556798
it("constructor preserves subclass fields while ignoring excess properties by default", () => {
67566799
class A extends Schema.Class<A>("A")({
67576800
a: Schema.String

0 commit comments

Comments
 (0)