Skip to content

Emit effect-app schema facades at .d.ts (Class/Error/Struct/Opaque)#3

Open
patroza wants to merge 24 commits into
mainfrom
r/dts-emit-more-ctors
Open

Emit effect-app schema facades at .d.ts (Class/Error/Struct/Opaque)#3
patroza wants to merge 24 commits into
mainfrom
r/dts-emit-more-ctors

Conversation

@patroza

@patroza patroza commented Jun 21, 2026

Copy link
Copy Markdown
Member

Emit compact effect-app schema facade declarations from the TypeScript declaration transformer.

What changes:

  • Materializes Class / Opaque / TaggedErrorClass schema declarations into facade-shaped .d.ts output.
  • Emits static namespace members for Encoded, Make, DecodingServices, and EncodingServices where the checker can serialize them.
  • Replaces legacy handwritten Encoded extends S.StructNestedEncoded<typeof SameModel> placeholders with the static generated Encoded interface.
  • Normalizes generated import types so existing namespace imports are preferred before falling back to import("...") type references.

Validation against scanner:

  • Built release tarball as effect-app/TypeScript@v6.0.3-effect-app.3 from this PR head (d26f6896f).
  • Installed scanner with the .3 tarball and ran /node_modules/.bin/tsc --version: Version 6.0.3.
  • Ran scanner api declaration build with MACS_TS_COMPILER=tsc node scripts/tsgo-or-tsc.mjs --build api/tsconfig.src.json --force --stopBuildOnErrors.
  • Result: build passes and api/dist has 0 remaining StructNestedEncoded placeholders.

Base:

  • This branch is based on real TypeScript 6.0.3 source.

typescript-bot and others added 11 commits February 9, 2026 01:19
…to release-6.0 (microsoft#63208)

Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Jake Bailey <5341706+jakebailey@users.noreply.github.com>
…to release-6.0 (microsoft#63246)

Co-authored-by: Jake Bailey <5341706+jakebailey@users.noreply.github.com>
…to release-6.0 (microsoft#63327)

Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
Co-authored-by: RyanCavanaugh <6685088+RyanCavanaugh@users.noreply.github.com>
…lease-6.0 (microsoft#63372)

Co-authored-by: Jake Bailey <5341706+jakebailey@users.noreply.github.com>
…to release-6.0 (microsoft#63407)

Co-authored-by: Jake Bailey <5341706+jakebailey@users.noreply.github.com>
@patroza patroza changed the title feat: facade S.Class/TaggedClass/ErrorClass/TaggedErrorClass models Emit effect-app schema facades at .d.ts (Class/Error/Struct/Opaque) Jun 22, 2026
@patroza patroza changed the base branch from codex/schema-dts-facade to main June 22, 2026 07:36
patroza and others added 7 commits June 22, 2026 09:45
…Class models

Extend the schema-model facade rewrite beyond the Opaque family to the
class and error families. Detection is now family-aware on the source heritage
constructor:

- S.Opaque / S.OpaqueFacade        -> S.OpaqueFacade
- S.Class / S.TaggedClass           -> S.OpaqueClassFacade
- S.ErrorClass / S.TaggedErrorClass -> S.OpaqueErrorFacadeClass

These class/error models emit an `S.EnhancedClass<Self, Schema, Inherited>`
base; the 3rd type arg (the brand, e.g. `Cause.YieldableError` for errors) is
extracted and preserved as the facade's Brand. The Opaque family keeps `{}`.

Validated on macs/scanner (static-OFF, 0 errors): 46 OpaqueErrorFacadeClass +
10 OpaqueClassFacade bases now faceted (were emitted as the full
`S.EnhancedClass<Self, S.Struct<...full...>>` before).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A `const X = S.Struct(...)` / `S.TaggedStruct(...)` model has no backing class,
so it is faceted on the const itself: the giant inline `S.Struct<{...}>`
annotation is replaced by a compact facade and the named member types are
attached via a sibling `interface X` (decoded Self) plus a TYPE-ONLY
`declare namespace X` (Fields/Encoded/Make/services). Both are type-space, so
they merge with the `const X` value without a value-space collision. The
source's `export type X = typeof X.Type` companion is dropped (the interface
replaces it).

Workflow compatibility: struct models are frequently workflow payloads, and the
Workflow types demand a concrete `S.Struct<Fields>` (AnyStructSchema +
`Struct<Fields & Context>` reconstruction). An `OpaqueFacade` is not a Struct
and breaks them, so the const is retyped to a scanner-local
`StructFacade<Self, Encoded, Make, DecodingServices, EncodingServices, Fields>`
(emitted as a self-contained `import("#lib/StructFacade").StructFacade<...>`
type) which is `Omit<S.Struct<Fields>, ...> & { pinned type-level members }` —
still a real struct schema, but with Type/Encoded/make/services resolved to the
named interfaces so consumers stop re-deriving them.

Member materialization uses a new EmitResolver method
`createTypeOfStructSchemaProperty`: it reads a property (Encoded / Type /
~type.make.in / DecodingServices / EncodingServices / fields) off the type of
the const's initializer and serializes the resolved type. Serializing the
resolved type keeps `never` services as `never` and never synthesizes
`S.Struct.*` references that could fail to resolve in a source file's scope.

Scanner src tree: 56 structs faceted, 0 errors (workflows/controllers/services
included). Function-returned structs (e.g. `addressWithMaxLength(...)`) are left
unfaceted, since their initializer is not a direct `S.Struct(...)` call.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The facade base is S.Bottom-based (not S.Class), so 'identifier: string' — an
S.Class/EnhancedClass static — was dropped from faceted class/error models.
Stock carries it via the EnhancedClass reference; add it to the facade static
members so the faceted type stays equal to stock. fields + the YieldableError/{}
prototype brand were already preserved.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…erface

identifier (generic string) now sits on OpaqueFacade/OpaqueClassFacade/
OpaqueErrorFacadeClass in effect-app (effect-app/libs), so the compiler must not
hand-emit it per model. Only per-model precise statics (fields/mapFields/to/from/
copy) stay compiler-emitted.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…type) + docs

Struct models now emit `S.StructFacade<X, X.Encoded, X.Make, X.DecodingServices,
X.EncodingServices, X.Fields>` via the file's own `S` import (StructFacade is
exported from effect-app >= 4.0.0-beta.279) instead of
`import("#lib/StructFacade").StructFacade<...>`. No scanner-local module needed.
Add docs/effect-schema-facade-emit.md (what/why/how/results + facade links).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@patroza patroza force-pushed the r/dts-emit-more-ctors branch from af09341 to 0f1017f Compare June 22, 2026 07:47
patroza and others added 6 commits June 22, 2026 10:30
…ss+Encoded/Struct)

Real stock-vs-patched output for each schema-model kind.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ache)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…tions

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants