Skip to content

_patches: layer the .d.ts-emit schema-facade emitter onto Effect-TS/tsgo#1

Open
patroza wants to merge 9 commits into
mainfrom
r/dts-emit-schema-facade-patches
Open

_patches: layer the .d.ts-emit schema-facade emitter onto Effect-TS/tsgo#1
patroza wants to merge 9 commits into
mainfrom
r/dts-emit-schema-facade-patches

Conversation

@patroza

@patroza patroza commented Jun 21, 2026

Copy link
Copy Markdown
Member

Layers the .d.ts-emit effect-app schema-facade emitter onto Effect-TS/tsgo (Effect LSP hooks + this) as three _patches/ entries.

Correctness, not just performance

Past the checker's instantiation/depth limits the schema generics silently degrade to unknown / anyDecodingServices/EncodingServices, constructor / make members, Type / Encoded — with no error reported. It is non-deterministic and worst under tsgo's default multi-threaded mode (each worker hits the wall independently). Materializing each view as a named static interface once at emit makes them fully resolved and stable for every program / project reference / worker; adopting it on the scanner surfaced several real bugs the silent any/unknown had masked.

  • Pins typescript-go at dc37b5249; additive, no overlap with Effect's _patches/001-028.
  • 029-transformers-declarations (declaration transformer), 030-checker-emitresolver (CreateTypeOf{Struct,Class}…Property), 031-printer-emitresolver.
  • Emits S.StructFacade / S.OpaqueClassFacade / S.OpaqueErrorFacadeClass / S.OpaqueFacade from effect-app (≥ 4.0.0-beta.280).

Fixes for newer effect Schema (effect@4.0.0-beta.85, #2442)

#2442 made the decoded .Type/.Encoded/.Make resolve to deferred mapped helpers (Struct.ReadonlySide<Fields, …>) instead of object literals. Restored static emit + closed two facade gaps:

  • Struct facades (030): expand CreateTypeOfStructSchemaProperty through createTypeLiteralOfType so Type/Encoded/Make stay static interfaces; 029 keeps the companion type X only when faceted (no orphan-drop → no value-only TS2749).
  • Class facades (030): CreateTypeOfClassStaticProperty likewise serialized via the node builder, so every faceted class's namespace degraded to mapped ReadonlySide aliases. Now object properties expand to static interfaces; callable members (never services, base mapFields/copy) keep their signatures via a has-properties guard.
  • Bare-imported classes (029): heritage detection only matched S.Class(...) — a bare import { Class } from "effect-app/Schema" (class X extends Class<X>(...)) was missed, leaving the base as a fully-inlined EnhancedClass<X, Struct<{…all fields…}>>. Now both heritage shapes facet to compact OpaqueClassFacade<X, X.Encoded, …>. On the scanner this removed all 14 EnhancedClass inlinings; ReadonlySide class-namespace aliases dropped to 0.

Release & version — effect-app.8

  • Binary version: 7.0.0-dev+effect-app.8 (upstream typescript-go 7.x base + +effect-app.N build metadata; bump N in etscheckerhooks/init.go).
  • _tools/cut-release.sh (pnpm release:cut): builds all platform binaries, packages the tsgo-<platform>[.exe].gz assets install-patched-compilers.mjs downloads, writes SHA256SUMS, creates the release; version derived from source. --dry-run / --skip-setup.
  • Released: https://github.com/effect-app/tsgo/releases/tag/v7.0.0-dev-effect-app.8 — consumed by macs/scanner (tsgoRepo: effect-app/tsgo, @latest).
  • Validated: patches apply in order; tsgo builds; macs/scanner pnpm check + pnpm lint --type-aware (api + e2e + frontend) 0 errors; struct & class facades emit static Type/Encoded/Make/Fields interfaces; 0 remaining EnhancedClass.

🤖 Generated with Claude Code

patroza and others added 5 commits June 22, 2026 14:58
Re-expresses our effect-app/typescript-go#2 feature (class/error/struct schema
facade declaration emit) as three `_patches/` entries, authored against the
exact `typescript-go` submodule commit this repo pins (dc37b5249) — the same
commit our codex baseline branched from, so they apply cleanly:

  029-transformers-declarations-effect-schema.patch  (declaration transformer)
  030-checker-emitresolver-effect-schema.patch        (CreateTypeOf* resolver)
  031-printer-emitresolver-effect-schema.patch         (EmitResolver interface)

The feature is purely additive (no overlap with Effect patches 001-028). After
`setup-repo` applies 001-031 and regenerates diagnostics, `go build ./cmd/tsgo`
yields a tsgo with Effect's LSP hooks AND our .d.ts emitter. Verified on the
macs/scanner src tree: 0 errors, 145 Effect LSP diagnostics (hooks live), and
56 StructFacade + 10 OpaqueClassFacade + 46 OpaqueErrorFacadeClass (emitter live).

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

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

Regenerate the .d.ts schema-facade patches verbatim from the canonical Go
implementation in effect-app/typescript-go PR Effect-TS#2 (head a9dd01c, base dc37b524 ==
this submodule pin), restoring four improvements the earlier partial port
dropped:
  - generated import normalization (prefer namespace imports over import("..."))
  - legacy `Encoded extends S.StructNestedEncoded` materialization
  - static-member rewriting (fields -> X.Fields, mapFields/copy signatures)
  - `Fields` interface in the generated namespace

029 transform.go +920 -> +1148; 030/031 unchanged in substance. Verified against
scanner api decl build: exit 0, 0 StructNestedEncoded placeholders, 415 `Fields`
interfaces emitted, Effect language service diagnostics live.

Set the binary version suffix to semver build metadata on the upstream 7.x base:
core.SetVersionSuffix("+effect-app.5") -> `tsgo --version` = 7.0.0-dev+effect-app.5
(replaces the old 0.14.x-effect-app.N scheme). Bump the counter per gz release.

Source: effect-app/typescript-go#2
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@patroza patroza force-pushed the r/dts-emit-schema-facade-patches branch from 833e8d2 to b3c2f3a Compare June 22, 2026 13:12
patroza and others added 4 commits June 22, 2026 17:26
Drop the `export type X = typeof X.Type` companion of a `const X = S.Struct(...)`
model only when the struct is actually faceted, and emit the decoded `Type` as a
`type X = …` alias when it does not materialize as an object literal (newer effect
Schema `.Type` resolves to a mapped type). Previously the builder bailed and the
companion was dropped with no replacement, leaving `X` value-only and breaking
cross-module `import { type X }` (TS2749) under faceted resolution.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
_tools/cut-release.sh (pnpm release:cut) builds every platform tsgo binary,
packages each as the gz asset that install-patched-compilers.mjs downloads,
writes SHA256SUMS, and creates the effect-app/tsgo GitHub release. The version is
derived from source (core version.go base + etscheckerhooks SetVersionSuffix) so
the tag, release title and binary --version cannot drift; --dry-run and
--skip-setup are supported.

Bumps the build counter to +effect-app.6 for the struct-facade companion-type fix.

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

createTypeOfStructSchemaProperty rendered the decoded property via TypeToTypeNode,
which under newer effect Schema types kept the deferred mapped helper (e.g.
`Struct.ReadonlySide<Fields, "Type">`) as a reference. That both regressed the
facade's static-interface output and left the top-level `Type` a non-literal, so the
struct facade builder bailed. Expand object-typed properties through
createTypeLiteralOfType — the same path the class/request facades already use — so
`X`, `Encoded`, `Make` and `Fields` emit as fully-expanded `interface`s; service
channels (resolve to `never`) keep their direct node form.

With static interfaces restored the declarations transformer no longer needs the
type-alias fallback (reverted); the companion-alias drop stays gated on a struct
actually being faceted. Bumps the build counter to +effect-app.7.

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

Recognize bare named-import heritage constructors (`import { Class } from
"effect-app/Schema"`) in addition to `S.Class(...)`, so those classes get the
compact `OpaqueClassFacade<X, X.Encoded, …>` base instead of an inlined
`EnhancedClass<X, Struct<{…}>>`.

Expand the class static properties (`Type`/`Encoded`/`Make`/`Fields`) to static
`interface`s in `CreateTypeOfClassStaticProperty`, the same way the struct-facade
path does — under effect #2442 these otherwise degrade to mapped `Struct.ReadonlySide`
aliases. Callable members (services `never`, base `mapFields`/`copy`) keep their
signatures via a has-properties guard. Bumps to +effect-app.8.

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.

1 participant