feat(declarations): materialize Effect schema model facades at .d.ts emit#2
Closed
patroza wants to merge 1 commit into
Closed
feat(declarations): materialize Effect schema model facades at .d.ts emit#2patroza wants to merge 1 commit into
patroza wants to merge 1 commit into
Conversation
…emit
Move the native model codegen's static schema types out of source and into the
declaration emitter. For standard struct models the emitter now:
- expands `interface Encoded extends S.StructNestedEncoded<typeof X>` into a
literal `interface Encoded { ... }` (nested models referenced by name)
- synthesizes `interface X` (Type) and `namespace X { Make; DecodingServices;
EncodingServices }` from the class schema
- rewrites the emitted `X_base` to
`S.OpaqueFacade<X, X.Encoded, X.Make, X.DecodingServices, X.EncodingServices, {}>`
intersected with the preserved statics (fields/mapFields/to/from/copy),
dropping the expensive `S.Struct<{ ...full schema... }>` from the base
Lives purely in declaration emit + checker/node-builder plumbing
(new EmitResolver methods) so it can be carried as a patch onto Effect's
TypeScript compiler fork.
Key correctness points: qualify nested refs with UseFullyQualifiedType; detect
the model from the base type's first type argument (the `_base` const has a
generated name); gate on the `S.{Opaque,OpaqueClass,OpaqueFacade,Class,
TaggedClass}` constructor; detect model namespaces by the presence of an
`interface Encoded` (path-1 strips the heritage before this pass runs).
Validated against macs/scanner (tsc 6.0.3, registry, --force, 0 errors):
no-static main + stock tsc = 16,644,980 instantiations; + this compiler =
13,108,430; static-native branch + stock tsc = 13,061,157 (~98.7% of the
in-source benefit captured).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Moves the native model codegen static schema types out of source and into the declaration emitter, so codegen can go back to text-only and the compiler materializes the full shape at
.d.tsemit. Based on v6.0.3 (release-6.0) to match the TypeScript version macs/scanner builds with.What it does (standard struct models)
interface Encoded extends S.StructNestedEncoded<typeof X>→ literalinterface Encoded { … }(nested models referenced by name, e.g.Address.Encoded).interface X(Type) +namespace X { Make; DecodingServices; EncodingServices }from the class schema.X_base→S.OpaqueFacade<X, X.Encoded, X.Make, X.DecodingServices, X.EncodingServices, {}>intersected with preserved statics (fields/mapFields/to/from/copy) — dropping the expensiveS.Struct<{ …full schema… }>from the base (the dominant instantiation lever).Lives purely in declaration-emit + checker/node-builder plumbing (new
EmitResolvermethods) so it can be carried as a patch onto the effect-app TypeScript fork.Gotchas baked in
NodeBuilderFlags.UseFullyQualifiedTypeon the materialization calls — without it nested refs collapse to a bareEncoded(1,412 errors)._baseconst has a generated, unreadable name).S.{Opaque,OpaqueClass,OpaqueFacade,Class,TaggedClass}(else non-schema classes likeContext.Serviceget a bogus facade).interface Encoded, not its heritage — the namespace pass strips theStructNestedEncodedheritage before this source-file pass runs (this previously silently disabled the base rewrite).Validation (macs/scanner, tsc 6.0.3, registry,
--force, 0 errors)→ ~98.7% of the in-source static benefit captured, soundly. Emitted
.d.tsis structurally equal to the native (in-source) codegen.Known WIP (not in this PR)
Bare
S.Opaque<X>models (no sourceEncodednamespace) are left as-is. Synthesizing their full namespace from the class is the next step; complex class-body models still error.Context + measurements: macs-holding/scanner#1597.
🤖 Generated with Claude Code