ReviewOS

home-lang/home

fix(ts): relate generic argument constraints across resolved placeholders

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

Problem

Home emits false TS2345 diagnostics when a method type parameter constrained to a class type parameter is passed to a built-in generic method whose parameter retains the class placeholder. A minimal strict repro uses a recursive generic interface:

interface State<Out = unknown> { output: Out }
type Standard<T> = { input: T; output: T };
interface SchemaType<Out = unknown, S extends State<Out> = State<Out>> {
  state: S;
  standard: Standard<this>;
}
class Registry<Schema extends SchemaType = SchemaType> {
  private map: WeakMap<Schema, boolean> = new WeakMap();
  add<S extends Schema>(schema: S) {
    this.map.set(schema, true);
    this.map.get(schema);
  }
}

TypeScript 6.0.3 and the TypeScript 7 native preview accept the source. Home reports one TS2345 at each call.

This surfaced after #662 gave WeakMap annotations their real key type; the pinned Zod graph has the same relationship in its registry.

Root cause

typeParameterConstraint returns a resolved placeholder target, while typeParameterConstraintAssignableToParamDepth compares that result against the method signature's potentially unresolved parameter placeholder. Recursive generic interface materialization makes those IDs differ even though they represent the same declared class type parameter, and the fallback structural relation rejects the recursive pair.

Fair oracle

Positive:

  • class type parameter constrained by a recursive generic interface;
  • method S extends Schema;
  • S passed to both WeakMap<Schema, V>#set and #get;
  • TypeScript 6.0.3 and TypeScript 7: 0 diagnostics;
  • Home parent: 2 false TS2345 diagnostics.

Negative control:

  • an unrelated primitive argument must remain TS2345.

Acceptance criteria

  • Compare resolved placeholder identities at the shared type-parameter constraint boundary.
  • Do not use type-parameter names, Zod symbols, source locations, or permissive widening.
  • Preserve rejection for unrelated arguments.
  • Add permanent regression coverage.
  • Verify the pinned Zod graph gains no candidate-only diagnostic identities.

Blocks the zero-addition admission gate for #662; tracks #416 and #548.

8 days ago

Root-cause correction: the ordinary call relation and overload applicability were already accepting the argument. The false TS2345 came from checkArgsAgainstSignatureWithMode's strict foreign-type-parameter diagnostic, which rejected every constrained source type parameter that did not share the target's name without first testing its transitive constraint chain.

The focused candidate now consults the existing recursive type-parameter constraint relation before emitting. The fair control is exact: S extends Schema passed to (value: Schema) => void is accepted, while number passed to the same target still emits the single expected TS2345. No type-name or corpus-specific special case is involved.

8 days ago

Implementation is live on main in a3a764a (fix(ts): honor transitive argument constraints (#664)).

Validation so far:

  • focused checker regression: pass; the suite observes exactly one TS2345, from the number negative control
  • standalone recursive-generic oracle: TypeScript 6.0.3, native TypeScript preview, and the optimized Home checker all report zero diagnostics
  • optimized production build: pass

I am keeping the issue open until the corpus differential, full suites, and linked benchmark documentation are published.

8 days ago

Completed on main in a3a764a; the combined published audit is in f26b768 and README. TypeScript 6.0.3, the native TypeScript preview, and ReleaseFast Home accept the transitive constrained-schema argument and retain exactly one matching TS2345 for the number control. The unchanged Zod 4.5.2 audit finishes at 430 diagnostics / 425 unique identities with zero candidate-only identities. Full checker and Program suites plus a clean-cache ReleaseFast build pass. Closing as completed.

Sign in to comment on this issue.