ReviewOS

home-lang/home

Fix mapped generic return instantiation from inferred tuple keys

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

Summary

Home leaves a mapped generic return type symbolic after call-site inference when its key domain is derived from an inferred readonly tuple. tsc and tsgo instantiate the return to the selected properties.

Reproduction

interface Entity<N extends number> {
  readonly id: N;
  readonly label: `entity-${N}`;
  readonly active: boolean;
}

type PickFields<T, K extends keyof T> = { readonly [P in K]: T[P] };

declare function project<T, K extends readonly (keyof T)[]>(
  value: T,
  keys: K,
): PickFields<T, K[number]>;

declare function field<T, K extends keyof T>(value: T, key: K): T[K];

const entity: Entity<1> = { id: 1, label: "entity-1", active: true };
const selected = project(entity, ["id", "label"] as const);
const label: "entity-1" = field(selected, "label");

Use strict, noEmit, and noLib with the benchmark's minimal global declarations.

Actual

Home reports:

TS2322: Type 'unknown[string]' is not assignable to type '"entity-1"'.
TS2345: Argument of type '"label"' is not assignable to parameter of type 'keyof PickFields'.

Expected

tsc 7.0.2 and tsgo 7.0.0-dev.20260707.2 both exit successfully and silently. Home should instantiate PickFields<T, K[number]> from the inferred T and readonly tuple K, making selected.label the literal type "entity-1".

Context

Found while adding the next fair generic-call inference workload under #416. The workload will not be accepted or timed until all three compilers validate the unchanged source graph successfully and silently.

8 days ago

Fixed and pushed to origin/main in e34242b.

The fix preserves K[number] while an array-constrained type parameter is still dependent, then materializes concrete primitive template-literal substitutions after inference. The regression asserts the projected object contains id/label, excludes active, and gives label the exact type "entity-1".

Verification:

  • focused inferred tuple-key checker regression
  • focused template-literal checker tests
  • full checker suite: 4,190 passed
  • full ts_driver suite
  • full ts_program suite
  • pre-existing generic NonNullable<T> regression after narrowing the preservation rule

Sign in to comment on this issue.