ReviewOS

home-lang/home

fix(ts): contextually type imported polymorphic mapped arguments

#619
Closed chris opened this 8 days ago ·
8 days ago

Parents: #548, #416

After #617, the pinned Zod 4.5.2 graph has 383 TS7006 diagnostics. The dominant cluster is 258 diagnostics in src/v4/classic/schemas.ts, primarily prototype method implementations passed to the imported core.$constructor generic through a homomorphic ProtoOf<t> mapped type.

A focused four-file strict NodeNext reduction isolates the general failure. The exported function receives an optional mapped prototype argument:

type ProtoOf<T> = {
  [K in keyof T]?: T[K] extends (...args: infer A) => infer R
    ? (...args: A) => R
    : T[K];
} & ThisType<T>;

When the explicit local type argument has both clone(): this and parse(data: string): number, one polymorphic this member prevents Home from contextually typing the unrelated parse implementation passed through the imported function. TypeScript 6.0.3 and native TypeScript 7.0.2 report exactly TS2339 for data.missing and TS2322 for a string return. Parent Home instead reports three TS7006 errors and four false TS2345 errors, while missing the required TS2339 and TS2322. Namespace-qualified and direct imports fail identically.

Root cause: indexed-access substitution conservatively preserved every T[K] when the concrete substituted object contained any polymorphic-this member, even when the exact selected member was independent. Imported generic instances also needed normalization before object-literal relation and diagnostic traversal. Resolve only exact selected members that do not themselves contain polymorphic this; keep direct polymorphic this[K] deferred. Normalize generic instances at the object relation/diagnostic boundary without changing normal assignability.

Do not special-case Zod, method names, or source spelling, and do not suppress diagnostics.

Required controls:

  • imported function reached through a barrel in namespace-qualified and direct forms;
  • explicit local type argument containing a polymorphic this-returning member and an unrelated ordinary method;
  • a matching type without the polymorphic member to prove the existing path remains intact;
  • deliberate missing-property and wrong-return implementations matching the reference diagnostic codes;
  • local/shadowed function names must not borrow imported Program facts;
  • repeated prepared-owner queries must not reparse or check owners;
  • exact same-parent Zod 4.5.2 ReleaseFast A/B with two deterministic runs, normalized diagnostic-set comparison, and zero additions before any timing claim.
8 days ago

Implementation and focused coverage are committed in small chunks:

  • 1f18348 — fix(ts): resolve polymorphic mapped argument members (#619)
  • 4fb9e17 — test(ts): cover imported polymorphic mapped arguments (#619)

Current verification:

  • focused local checker regression: exact TS2339 + TS2322, no TS7006/TS2345
  • strict four-file direct + namespace barrel reduction: Home matches TypeScript 6.0.3 and native TypeScript 7.0.2 on the exact code multiset (TS2339 + TS2322)
  • richer Zod-shaped constructor reduction: exact code multiset TS2322 + TS2339 across all three compilers
  • ts_program suite: 172/172
  • ts_checker suite: 4,334/4,334
  • debug tracing removed; git diff hygiene clean

Next: exact-parent ReleaseFast Zod 4.5.2 A/B and normalized diagnostic-set audit before documentation or timing claims.

8 days ago

Exact-parent Zod 4.5.2 ReleaseFast audit is complete for the final candidate.

Correctness:

  • exact parent 77deef9: 1,088 diagnostics
  • candidate: 976 diagnostics
  • normalized location/code comparison: 0 additions, 112 removals
  • TypeScript 6.0.3 oracle: 0 diagnostics
  • both minimized imported mapped-argument cases match TypeScript 6.0.3 and native TypeScript 7.0.2 on diagnostic codes and locations

Performance:

  • exact parent runs: 9.28s and 10.57s wall
  • exact parent under current load: 9.95s wall
  • candidate runs: 6.00s and 5.48s wall
  • mean wall time: 9.925s to 5.74s, 42.2% faster
  • candidate diagnostic identities were byte-identical across both runs

Regression gates:

  • ts_program: 172/172
  • ts_checker: 4,334/4,334
  • scoped pickier on changed files: pass
  • repository-wide pickier remains red on pre-existing vendored/upstream findings
  • git diff --check: pass

The accepted implementation avoids whole-type approximation: it resolves literal-key indexed chains one member at a time, retains polymorphic this when the selected member needs it, preserves direct overload sets for last-signature inference, and projects only the requested inherited member through imported interface heritage.

8 days ago

Shipped directly to origin/main in five linked commits:

  • 7367d76 fix(ts): resolve polymorphic mapped argument members (#619)
  • 7ada181 test(ts): cover imported polymorphic mapped arguments (#619)
  • 387144d fix(ts): preserve mapped receiver context (#619)
  • 5bc9f03 test(ts): cover inherited mapped receivers (#619)
  • ad4ae62 docs(ts): record mapped receiver benchmark (#619)

Post-rebase verification on current main: Program 172/172, checker 4,334/4,334, Zig formatting, scoped pickier, diff checks, and ReleaseFast build all pass.

The documented exact-parent Zod 4.5.2 A/B remains 1,088 → 976 diagnostics with zero additions and 112 removals; mean wall time 9.925 s → 5.740 s (42.2% lower). This is explicitly a same-correctness Home A/B, not a cross-compiler speed admission.

Sign in to comment on this issue.