ReviewOS

home-lang/home

fix(ts): preserve contextual generic constructor callback types and getter errors

#820
Closed glennmichael123 opened this 9 days ago ·
9 days ago

Parent: #548. Related: #758, #765 (different callback/forward-declaration failures).

Reproducible gap

On the unchanged pinned Zod 4.5.2 21-file core proxy, Home origin/main reports a Home-only core/schemas.ts:4879:19 TS2741 at util.defineLazy(inst._zod, "innerType", getter) inside $ZodLazy's generic constructor callback. TypeScript 6.0.3 and native TypeScript 7.0.2 do not report it. The proxy's only shared diagnostic is core/index.ts:11:26 TS2307 because it intentionally omits locales.

The relevant general shape spans imported declarations:

// core.ts
export interface Trait { _zod: { def: any; [key: string]: any } }
export interface Constructor<T extends Trait, D = T["_zod"]["def"]> {
  new (def: D): T;
  init(inst: T, def: D): asserts inst is T;
}
export declare function makeConstructor<T extends Trait, D = T["_zod"]["def"]>(
  name: string, initializer: (inst: T, def: D) => void
): Constructor<T, D>;

// util.ts
export declare function defineLazy<T, K extends keyof T>(object: T, key: K, getter: () => T[K]): void;

// main.ts
import * as core from "./core.js";
import * as util from "./util.js";
interface Inner extends core.Trait { _zod: { def: { type: "inner" } } }
interface Lazy extends core.Trait { _zod: { def: { type: "lazy" }; innerType: Inner } }
declare const inner: Inner;
export const good: core.Constructor<Lazy> = core.makeConstructor("Lazy", (inst, def) => {
  util.defineLazy(inst._zod, "innerType", () => inner);
});
export const bad: core.Constructor<Lazy> = core.makeConstructor("Bad", (inst, def) => {
  util.defineLazy(inst._zod, "innerType", () => 123);
});

The pinned TypeScript controls accept good and report TS2322 for the deliberate bad getter. An uncommitted Home experiment that clears the provisional TS2741 removes the false positive but also leaves bad without TS2322. That experiment is not an accepted fix. The callback must retain the concrete Lazy argument (including innerType) through contextual result typing, import transfer, generic substitution, and the nested T[K] getter check.

Acceptance

  • Match both controls on the positive and negative cross-file reduction, including the invalid getter's TS2322. Include a case with asserts inst is Base before defineLazy and prove it does not discard Lazy's specific members.
  • Remove core/schemas.ts:4879:19 TS2741 on the unchanged frozen core proxy with zero new path/line/column/code identities. Do not suppress a diagnostic unless the final contextual pass can re-emit all genuine errors.
  • Add permanent checker and Program positive/negative regressions; run the full relevant suites, guarded optimized build, exact normalized Zod comparison, formatting, and Pickier for touched docs.
  • Keep this linked to #548. Do not claim full 106-file Zod admission or speed until its separate gates pass.

No Zod path/name/property special cases, diagnostic deletion as a standalone fix, source edits, skips, or benchmark filtering.

9 days ago

Implemented and verified by fe6535c32 (authored and committed by glennmichael123). The commit preserves concrete contextual constructor callback arguments through imported generic substitution, keeps invalid indexed getter returns as TS2322, and adds permanent checker plus three-file Program positive/negative regressions, including the assertion-signature path. docs/docs/TS_PERFORMANCE.md records the successful guarded complete checker suite, ReleaseSafe CLI build, exact frozen-core comparison, and two-control oracle. A fresh run today was serialized under the 3,840 MB guard and hit only its fixed 30-minute wall-clock bound during a cold build; it did not exceed memory, and no code changed during that rerun.

Sign in to comment on this issue.