{{ message }}
Migrate operations/helpers.js to TypeScript - #2206
Merged
Merged
Conversation
jdeniau
force-pushed
the
extract-mixin-operations
branch
2 times, most recently
from
June 1, 2026 20:40
4c79bfe to
c901901
Compare
jdeniau
force-pushed
the
migrate-operations-helpers
branch
from
June 1, 2026 20:49
f7b1d31 to
4ad1555
Compare
Type the shared operation helpers precisely, anticipating that the rest of operations/ will become TS and consume them under strict checking: - reify<C extends CollectionImpl<unknown, unknown>>(iter: C, seq): C — preserves the kind of `iter`, so the many "same-type" call sites (reverse/slice/sort/ skipWhile/…) stay cast-free. The dynamic create/constructor reconstruction is asserted once, internally, at that type-erasure boundary. - defaultComparator(a: unknown, b: unknown) — accepts unknown so it is assignable as a Comparator<V> for any value type (contravariance), avoiding a future mismatch when sortFactory is typed. - makeSequence / collectionClass / cacheResultThrough typed against the source. map and flip return a transformed type, so they now use the overload + loose `): unknown` implementation pattern (as filter already does) to stay cast-free. Imports of './helpers.js' in the still-JS operations files are made extensionless so they resolve to the new .ts. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
jdeniau
force-pushed
the
migrate-operations-helpers
branch
from
June 1, 2026 20:49
4ad1555 to
8333522
Compare
Type the 14 operation factories precisely so reify can carry the result type. - reify is now reify<S extends CollectionImpl<unknown, unknown>>(iter, seq): S — it follows the type of `seq`. The precision therefore lives in each factory's return type: same-kind factories (reverse/slice/sort/filter/skipWhile/ takeWhile/interpose) are <C extends CollectionImpl<...>>(collection: C, …): C, while transforming factories return the precise transformed type (mapFactory → CollectionImpl<K, M>, flipFactory → KeyedCollectionImpl<V, K>, …). - As a result `map` and `flip` in Collection.ts are clean single signatures again (no `): unknown` implementation overload needed). - makeSequence / collectionClass are overloaded per collection kind. The factory bodies build a sequence by dynamically mutating the makeSequence result and drive the input through its dynamic iteration protocol (the `IteratorType` union, unknown keys/values). That construction is not expressible in the type system, so casts are confined to that boundary: a `loose()` view of the input, the `MutableSequence` shape of the built sequence, and the return. No `any` anywhere; the exported signatures are fully precise. `interleave` keeps an overload + loose implementation since its result flows through `flatten` (which widens to CollectionImpl<unknown, unknown>). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add a public `__iterator(type: IteratorType, reverse?): IterableIterator<K | V | [K, V]>` overload on CollectionImpl (promoting the existing implementation signature). Operation factories forward a runtime `type` to `__iterator`, which previously matched none of the literal overloads and forced a loose `unknown`-typed view of the input. With it, the `__iteratorUncached` bodies now iterate through the precisely-typed `collection` directly: literal `ITERATE_ENTRIES` calls yield `[K, V]` steps, so the per-element `entry[0] as K` / `entry[1] as V` / `value as V` / `key as K` casts are gone. `loose()` is now only used for `get`/`has`/`includes`/`reverse`/ `flip` (which take `unknown` keys / non-base members), and `LooseInput` no longer declares `__iterator`. A few structural iterator-boundary casts remain because `collection.__iterator` returns a native `IterableIterator` (immutable's `Iterator` class type is frozen) and a `step` object is reused across output types. Those, the `makeSequence`/return construction boundary, and the `unknown`-key `get`/`has` will only fully clear up once the operation sequences become real typed classes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…uence.js migration to TS
jdeniau
force-pushed
the
migrate-operations-helpers
branch
from
June 8, 2026 06:50
822c3cf to
226429a
Compare
jdeniau
pushed a commit
to jdeniau/immutable-js
that referenced
this pull request
Aug 16, 2026
Each finding from .agents/migration-status.md was traced back to its originating PR, then fixed or confirmed as an intentional change: - R1 (isSubset string argument, from immutable-js#2204): keep the new character-iteration semantics, consistent with isSuperset and with Collection('abc'); documented as a v6 breaking change in the CHANGELOG and pinned by multi-char unit tests. - R2 ('@@iterator' fallback removal, from immutable-js#2127): confirmed intended modernisation; explicit CHANGELOG entry, and the two immutable.d.ts docstrings no longer mention @@iterator. immutable.js.flow is left untouched since Flow's @@iterator syntax denotes Symbol.iterator. - R3 (reverseFactory reverse-iteration keys, ?? 0 from immutable-js#2206, NaN keys already in v5): fixed by counting down from the number returned by ensureSize(collection) - the reversed sequence has the same size as its source. Regression tests cover both __iterate (reduceRight) and __iterator (keyed reverse) paths; CHANGELOG entry since the NaN behaviour shipped in v5. - R4 (wholeSlice with begin === undefined, from immutable-js#2128): restored the faithful v5 form (begin !== undefined && begin <= -size) so slice() with no arguments goes through sliceFactory again, on empty collections too; identity regression test added. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0122shfP2ngkkjuXZBWoeFGW
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Migrates
src/operations/helpers.js→helpers.ts, as part of the v6 TS migration.Stacked on #2193 (base:
extract-mixin-operations).Typing decisions
Typed precisely with the end-state (all of
operations/in TS) in mind, so theremaining files consume these helpers cleanly under strict checking later:
reify<C extends CollectionImpl<unknown, unknown>>(iter: C, seq): C—preserves the kind of
iter, keeping every "same-type" call site inCollection.ts(reverse/slice/sort/skipWhile/interpose/…) cast-free.The dynamic
create/constructorreconstruction is asserted once, internally,at that type-erasure boundary.
defaultComparator(a: unknown, b: unknown)—unknownparams make itassignable as a
Comparator<V>for any value type (contravariance), avoiding afuture mismatch when
sortFactoryis typed.makeSequence/collectionClass/cacheResultThroughtyped against thesource (precise factory union, structural
this).mapandflipreturn a transformed type, so they adopt the overload + loose): unknownimplementation pattern (asfilteralready does) — cast-free.'./helpers.js'imports in the still-JS operations files are made extensionlessto resolve against the new
.ts.Verification
npm run type-check— 0 errorsnpm run test:unit— 783 passednpm run build— OK (no load-order cycle)npx tstyche— 828 passed