Conversation
|
Bundle Size AnalysisGenerated from PR build output; treat the content below as untrusted.
|
|
I'm not convinced there is an actual missing use case here. Can't the nested case already be handled by defining The PR's example creates |
I understand what you're saying. You're right. I screwed up my explanation and my example. class Foo extends Schema.Class<Foo>('Foo')(
Schema.Struct({
a: Schema.String,
})
) {}is valid syntax, it would be logical to assume that class Foo extends Schema.Class<Foo>('Foo')(
Schema.Struct({
a: Schema.String,
}).pipe(Schema.encodeKeys({ a: 'c' }))
) {}would likewise be valid syntax, if one needs different encode keys. |
|
I ended up encountering a few other Schema use cases, besides Thanks for the comments! |
Type
Description
Fixes a TypeScript overload error when a
Schema.Structtransformed bySchema.encodeKeysis passed directly toSchema.Class.fails to type-check:
despite working correctly at runtime —
Schema.decodeUnknownSync(Foo)/Schema.is(Foo)etc. all behave as expected once the type error is silenced. The root cause is thatSchema.Class's struct overload requires the literalStruct<Fields>interface, butencodeKeys's return type only extendsdecodeTo<To, From>, which doesn't exposefields/mapFields— even thoughencodeKeys'stoside is structurally just the original struct.That pattern is fine when a single top-level rename is needed and the caller controls the decode/encode call site directly. It doesn't work when the rename needs to live on a nested field's own struct definition (e.g. a child class embedded inside a parent, where the child's schema is what's passed to the parent's
Classconstructor) or when multiple nested schemas needencodeKeys. These are the use cases this PR aims to fix.Changes
encodeKeys's returned schema now carries a real.fieldsproperty (mirroring the original struct's fields) and a private type-id brand (EncodeKeysTypeId, following the existingflip/FlipTypeIdpattern), so it satisfies the structural shapeClassneeds.Class's struct overload, its interface,makeClass, and the internalisStructguard are widened to acceptStruct<Fields> | encodeKeys<Struct<Fields>, any>in the relevant positions.Class.mapFieldsnow delegates to the underlying struct (struct.to) when built from anencodeKeysschema, sinceencodeKeysresults don't have their own runtimemapFields.Class.extendexplicitly throws when called on a class built from anencodeKeysschema, rather than silently reconstructing the class without the key mapping.extendmerges fields viaSchemaAST.struct(...)from scratch, which has no way to carry the original rename forward — attempting to support it correctly would mean re-deriving a newencodeKeysmapping that also covers newly added fields, which is a separate, larger feature. I'd rather fail loudly here than ship something that silently drops the rename.Scope
This fixes
Schema.Classonly.Schema.TaggedClass,Schema.Error, andSchema.TaggedErrorshare the same overload shape and would need the identical treatment if this pattern is wanted there too — happy to extend this PR to cover them if that's preferred, or leave it to a follow-up.Verification
Schema.isSchemarecognizes a class built from anencodeKeysschema.make/Equal.equals/ arbitrary generation / decode success & failure / encode success & failure round-trip for a class built from anencodeKeysschema.mapFieldsworks correctly on such a class.extendthrows with a clear error message on such a class.> pnpx vitest run packages/effect/test/schema/Schema.test.ts Test Files 1 passed (1) Tests 600 passed (600)