ReviewOS

home-lang/home

fix(ts): transfer Record and utility types across files, and reduce mapped types over any

#764
Closed glennmichael123 opened this 8 days ago ·
8 days ago

Parent: #758 · Related: #548

core/api.ts:1784 and :1785 report a false TS7006 on v in truthyArray.map((v) => ...). The receiver is any, and TypeScript reports TS7006 on an any receiver too, so the diagnostic is correct and the cause is upstream: util.normalizeParams(_params) types as any across files. Three independent defects each keep it any:

  1. Cross-file transfer of Record and utility types. Normalize<T> uses Record<any, any> and util's own Omit<T, K> = Pick<T, Exclude<keyof T, K>>. program_schema.zig pendingSupported rejects .record (unless readonly) and .utility (unless extract/exclude), so the declaration degrades to an opaque leaf and lowers to any. The consumer rejects them as well (lowerProgramExpression: .partial/.required/.readonly/.pick/.omit, and a .record with a non-string/number/symbol key).
  2. Record<any, V> lowers to any. The builtin Record lowering handles string/number/symbol/generic/literal/enum keys but not any. tsgo maps an any key to a string index signature (Any|String -> stringType). As a result T extends Record<any, any> behaves as T extends any.
  3. A homomorphic mapped type instantiated with any (zod's Flatten<T> = Identity<{ [k in keyof T]: T[k] }>) yields { [x: string]: any[k] } instead of { [x: string]: any }: the key parameter is never substituted into the index value and any[k] is not reduced. This also drives the three sibling false TS2411s at api.ts:1760/1761/1767. Regression shape to pin: import * as u from "./u.js"; type I<T>=T; type F<T>=I<{[k in keyof T]:T[k]}>; interface X extends F<any> { a?: string[] } must not report TS2411.

Fixing (1) widens transfer for every cross-file declaration that currently degrades, so it needs the same A/B discipline as #754. An adversarial check found that (1)+(2) alone do not clear the corpus sites; (3) is required.

8 days ago

The preceding imported-value cause is complete in cdad20fe5d. The unchanged Zod v4.5.2 core shard is now 43 diagnostics with 2 TS7006, both owned here: api.ts:1784:36 and api.ts:1785:34. The candidate removed only #763's two identities and added none, so this issue is now the last remaining cause under #758.

8 days ago

Measured and rejected the first complete transport candidate; no source changes were retained.

The candidate admitted Record<any, v> plus all homomorphic utilities into ordinary Program declarations, lowered Partial/Required/Readonly/Pick/Omit as mapped types, reduced Record<any, v> to a string index, and reduced Program any[K] to any.

Results:

  • Broad admission regressed 7/218 Program/class-schema tests by converting protected contextual projections into ordinary whole types.
  • Narrowing admission to the Record<any, v> graph restored all 217 existing Program tests, but the new focused oracle still produced TS2339 + TS7006 instead of TypeScript's single deliberate TS2322.
  • On unchanged Zod v4.5.2 core, the narrowed candidate moved 43 → 129 diagnostics: it removed nothing and added 86 TS2698 spread errors across normalizeParams call sites.
  • The entire candidate was removed, the worktree returned clean, and origin/main remains exactly cdad20f.

The next design must preserve deferred homomorphic identity through alias instantiation rather than materializing an approximate mapped return at the Program boundary. The existing contextual projection behavior for Record<string, unknown> graphs is a hard regression gate.

8 days ago

Landed the safe local semantic foundation in 5fc16f92e, pushed directly to origin/main as Chris Breuer without coauthors.

This batch now:

  • lowers Record<any, V> to TypeScript's string-key domain while retaining V instead of erasing the record to any;
  • reduces completed any[K] indexed templates after mapped-key substitution, including the homomorphic Identity<{ [K in keyof T]: T[K] }> form;
  • adds focused checker regressions for both behaviors.

Validation:

  • checker: 4,381/4,381;
  • Program: 217/217;
  • ReleaseFast home-tsc build passed;
  • focused TypeScript 6.0.2 oracle and Home emit the same two deliberate TS2322 diagnostics, with no TS2411, TS2339, or TS7006;
  • unchanged Zod v4.5.2 core remains exactly 43 diagnostics, with normalized identity diff 0 removed / 0 added against the accepted baseline;
  • Zig formatting, focused Pickier, and git diff --check passed.

The unchanged Zod result is intentional evidence that this local fix does not repeat the rejected 86-TS2698 regression. The remaining work is still the cross-file transport of the deferred conditional/mapped graph used by normalizeParams; the two TS7006 sites at api.ts:1784:36 and api.ts:1785:34 remain. This issue stays open.

8 days ago

Measured and rejected a second cross-file transport design; no candidate source changes were retained, and origin/main remains exactly 5fc16f92e.

The candidate extended the existing contextual read projection instead of broadly admitting utility graphs. It preserved Normalize<T>'s undefined/object filters as deferred conditionals, carried finite Pick/Omit keys, resolved mapped templates through their binding environment, and allowed conservative omitted surfaces through intersections only for function results.

Evidence:

  • reduced direct Omit, Flatten<Omit>, mapped-over-Omit, and the complete Normalize intersection oracle all matched TypeScript 6.0.2 with the same single deliberate TS2322;
  • all 218 pre-existing Program/class-schema tests passed before the final intersection step;
  • unchanged Zod tsconfig.api.json then crashed deterministically 4/4 with exit 139 and no diagnostics;
  • the macOS crash report identifies EXC_BAD_ACCESS while traversing Checker.iterableElementType union members, with concurrent checker workers also inside virtual-module/type lowering;
  • the candidate diff and crash report were preserved outside the repository for diagnosis, all four modified source files were restored to HEAD, and generated .zig-cache data was deleted.

A focused pass is insufficient for this path. The next design must preserve deferred filtered-member lookup without materializing a generic mapped/conditional type that can corrupt or outlive its checker-local pool in the full parallel Program graph. This issue remains open; no crash output is counted as diagnostic progress.

8 days ago

Landed the deferred imported Normalize read path in 6f26046, with the evidence and reproduction record in 3e764c0. Both commits are on origin/main.

The implementation keeps the filtered mapped/conditional declaration in its source Program graph, assigns the result a checker-local identity, and resolves only requested members from the concrete substituted arguments. It does not publish the whole mapped type across checker pools, which was the ownership failure behind the earlier 4/4 crash candidate. Homomorphic mapped identities reduce to their source after instantiation.

Acceptance evidence:

  • unchanged two-file reduction: TypeScript 6.0.3, native TypeScript 7.0.2, ReleaseSafe Home, and ReleaseFast Home all emit zero diagnostics;
  • permanent positive/negative Program controls forbid TS2411 and TS7006 and retain exactly 2 deliberate TS2322 diagnostics;
  • Program suite: 220/220;
  • checker suite: 4,395/4,395;
  • unchanged Zod 4.5.2 core: 13 diagnostics / identities at parent e32642e to 8 at 6f26046;
  • exact removals: api.ts:1760:3, 1761:3, and 1767:3 TS2411 plus 1784:36 and 1785:34 TS7006;
  • additions: 0;
  • ReleaseSafe Zod gate: 4/4 normal exits with byte-identical identity hash 1e17af71d03b553a5f036464f6fc787dc2b6540936085ce1ac5d3d25fabd918b;
  • ReleaseFast reproduced the same 8-identity set;
  • stripped ReleaseSafe and ReleaseFast builds passed under the 3,840 MB guard, peaking at 2,766 MB and 2,866 MB.

This completes the measured #764 acceptance surface without skips, corpus edits, stubs, benchmark-specific cases, or a timing claim. Leaving issue closure to the maintainer.

8 days ago

Completed in 6f26046 and documented in 3e764c0; both commits are ancestors of current origin/main.

Acceptance evidence:

  • unchanged pinned Zod 4.5.2 core shard: 13 -> 8 diagnostics/identities, exactly 3 TS2411 + 2 TS7006 removed and zero added;
  • focused valid Normalize/Record/utility/mapped/conditional oracle is clean in TypeScript 6.0.3, native TypeScript 7.0.2, ReleaseSafe Home, and ReleaseFast Home;
  • permanent positive/negative Program controls retain the intended two TS2322 negatives while forbidding TS2411/TS7006;
  • Program 220/220 and checker 4,395/4,395 at the checkpoint;
  • guarded stripped ReleaseSafe and ReleaseFast builds passed at 2,766 MB and 2,866 MB peaks under the fixed 3,840 MB ceiling;
  • four serial ReleaseSafe Zod runs were byte-identical and ReleaseFast reproduced the same normalized identity set.

The implementation uses deferred source-owned member reads and checker-local identities; it does not special-case Zod, source paths, member names, or diagnostic codes, and it does not edit or suppress the corpus.

Sign in to comment on this issue.