ReviewOS

home-lang/home

fix(ts): model iterator helper methods on iterator receivers

#969
Open glennmichael123 opened this 4 days ago ·
4 days ago

Related: #960, #66.

TypeScript 5.7.3 declares iterator helpers on IteratorObject<t>, not Array<t>. A control using [1,2,3].values().filter(...).map(...).toArray() has an iterator after filter/map and an array only after toArray. Home currently accepts the chain because lib.arrayProto incorrectly has a toArray method. Removing that member exposes the real gap: checker treats the iterator object (which stores its yielded T in a numeric index slot) as an array, so filter returns T[] and map follows Array semantics. The full checker test checker: ES2025 Float16Array global and iterator helper toArray are recognized failed after removing the erroneous Array method (4733 pass / 1 fail). That removal is not yet committed.

Fix the underlying type model: recognize IteratorObject receivers before array-prototype fallback, give filter/map/take/drop/toArray and other helpers the TypeScript iterator return/callback types, preserve generic inference, and ensure Array<t> itself has no toArray. Compare TypeScript 5.7.3 controls for iterator chains and direct array.toArray, then run checker, Program, LSP and exact CLI tests under the memory guard. No name-based diagnostic suppression or Array-only proxy method.

1 day ago

Pushed 633d89948 and 40ca6404c to main. The iterator receiver now carries the rest of TypeScript 5.7.3's IteratorObject surface, not just map / filter / take / drop / toArray.

Added with their declared callback and result types: flatMap (its callback may return an iterator or an iterable of U), reduce, forEach, some, every, find, the type-predicate overloads of filter and find, and the readonly [Symbol.toStringTag].

A lazily synthesized member cannot carry an overload set — the helpers have to be built per lookup, because each result is another iterator with helpers — so the two overloaded helpers are resolved where TypeScript resolves them:

  • reduce is selected by argument count before the callback is contextually typed. With no initial value it accumulates in T (TypeScript's first two overloads); with one it binds its own U from that argument. The selected signature is recorded on the callee node, so the callback's parameters are (acc: T, value: T, index: number) and a body error such as acc.toUpperCase() reports TS2339 exactly as TypeScript does.
  • filter and find keep the ordinary signature — both overloads type the argument identically — and the result is narrowed from the argument's own predicate target, whether that is a function expression or a reference to a declared guard.

Two further corrections came out of the matched controls:

  • toArray() now returns a type with array provenance, so a mismatch elaborates through the element (Type 'string' is not assignable to type 'number'.) instead of 'number' index signatures are incompatible.
  • The built-in iterators had no display name at all, so TS2339 on an iterator receiver rendered does not exist on type. with no type. values(), keys(), entries() and [Symbol.iterator]() are now named ArrayIterator<T> (MapIterator / SetIterator for those collections), and every helper result is named IteratorObject<T, undefined, unknown>, with the type arguments recorded so instantiation re-renders the name.

New exact-stream oracles under packages/ts_cli/testdata/issue969-iterator-helpers, each byte-identical to TypeScript 5.7.3: helpers.ts (every helper with a correct annotation, both engines silent), wrong.ts (twelve TS2322 diagnostics pinning each result type and the IteratorObject<number, undefined, unknown> display of take / map / filter), errors.ts (TS2554 arity including reduce's 1-2 range, TS2339 naming the ArrayIterator<number> receiver, and the [Symbol.toStringTag] assignment), and guards.ts (named and inline type predicates narrowing both filter and find).

Gates under the 3,840 MB guard: direct checker 4,757/4,757, Program 473/473, expanded exact-stream audit 165 streams, 163 exact matches (the two mismatches are #975's imported-union display order, unchanged by this batch). The guarded LSP step could not run on this host: the ts_lsp debug compile measures 3,961 MB at 8 shards and 4,006 MB at 16, so it exceeds the ceiling regardless of sharding (exit 125) — an artifact-compile footprint in the same class as #855.

One gap found while writing the controls is worth tracking separately: Home does not gate these helpers on the selected library, so values().toArray() resolves under lib: ["es2023"] where TypeScript reports TS2339. The same holds for other post-ES2023 globals such as Float16Array, so it is a library-selection question rather than an iterator one. Also still open here: next() models { value: T; done: boolean } rather than TypeScript's IteratorResult<T, TReturn> union.

4 days ago

Pushed 256d787 and 347f3ec. Array<t> no longer exposes iterator-only toArray; iterator receivers are recognized before numeric-index array fallback. Iterator filter preserves yielded T, generic map yields an iterator of U, and toArray returns U[]. Added a checker test for the typed chain and the missing direct Array method, plus an exact TypeScript 5.7.3 CLI fixture. Direct checker: 4,735/4,735 passed; the new CLI fixture matches tsc's TS2339 exactly. The expanded 140-project audit and Program/LSP runs await memory headroom. This issue stays open for the remaining IteratorObject helper methods and overload/type precision. Related #960.

4 days ago

Final gates for the current batch: direct checker 4,735/4,735; TypeScript 5.7.3 exact CLI audit 140/140; guarded Program step passed; guarded exact LSP step passed; targeted pickier passed. Latest pushed main commit: 3f68c9b. The checkout has only pre-existing unrelated untracked files. Keeping this issue open for the remaining behavior noted above.

Sign in to comment on this issue.