diff --git a/.changeset/fix-variant-schema-default-cache.md b/.changeset/fix-variant-schema-default-cache.md new file mode 100644 index 00000000000..4449cb1754e --- /dev/null +++ b/.changeset/fix-variant-schema-default-cache.md @@ -0,0 +1,5 @@ +--- +"effect": patch +--- + +Separate the default `VariantSchema` cache from named variant entries. diff --git a/packages/effect/src/unstable/schema/VariantSchema.ts b/packages/effect/src/unstable/schema/VariantSchema.ts index 2ab7260e54e..895a17ef650 100644 --- a/packages/effect/src/unstable/schema/VariantSchema.ts +++ b/packages/effect/src/unstable/schema/VariantSchema.ts @@ -26,6 +26,7 @@ import * as Struct_ from "../../Struct.ts" export const TypeId = "~effect/schema/VariantSchema" const cacheSymbol = Symbol.for(`${TypeId}/cache`) +const defaultCacheSymbol = Symbol.for(`${TypeId}/defaultCache`) /** * Pipeable container of schema fields that can be extracted into per-variant @@ -38,6 +39,8 @@ export interface Struct extends Pipeable { readonly [TypeId]: A /** @internal */ [cacheSymbol]?: Record + /** @internal */ + [defaultCacheSymbol]?: Record } /** @@ -214,10 +217,11 @@ const extract: { readonly isDefault?: boolean | undefined } ): Extract => { - const cache = self[cacheSymbol] ?? (self[cacheSymbol] = Object.create(null)) - const cacheKey = options?.isDefault === true ? "__default" : variant - if (Object.hasOwn(cache, cacheKey)) { - return cache[cacheKey] as any + const cache = options?.isDefault === true + ? self[defaultCacheSymbol] ?? (self[defaultCacheSymbol] = Object.create(null)) + : self[cacheSymbol] ?? (self[cacheSymbol] = Object.create(null)) + if (Object.hasOwn(cache, variant)) { + return cache[variant] as any } const fields: Record = {} for (const key of Object.keys(self[TypeId])) { @@ -243,7 +247,7 @@ const extract: { } } const schema = Schema.Struct(fields) - cache[cacheKey] = schema + cache[variant] = schema return schema as any } ) diff --git a/packages/effect/test/unstable/schema/VariantSchema.test.ts b/packages/effect/test/unstable/schema/VariantSchema.test.ts index ebb903aef79..9d6bc6e3f3d 100644 --- a/packages/effect/test/unstable/schema/VariantSchema.test.ts +++ b/packages/effect/test/unstable/schema/VariantSchema.test.ts @@ -62,6 +62,25 @@ describe("VariantSchema", () => { assert.deepStrictEqual(Object.keys(Test.extract(struct, "a").fields), ["value"]) }) + + it("does not collide the __default variant with the default-schema cache entry", () => { + const Test = VariantSchema.make({ variants: ["a", "__default"], defaultVariant: "a" }) + const defaultFirst = Test.Struct({ + value: Test.Field({ a: Schema.String, __default: Schema.Number }) + }) + + Test.extract(defaultFirst, "a") + + assert.strictEqual(Test.extract(defaultFirst, "__default").fields.value, Schema.Number) + + const namedFirst = Test.Struct({ + value: Test.Field({ a: Schema.String, __default: Schema.Number }) + }) + + Test.extract(namedFirst, "__default") + + assert.strictEqual(Test.extract(namedFirst, "a").fields.value, Schema.String) + }) }) describe("Model", () => {