fix: sequential toValue, plain-object guard in iterate, real coverage#6
Merged
winton merged 2 commits intoApr 9, 2026
Merged
Conversation
- toValue now iterates all input types sequentially so stateful async reductions are always deterministic (previously arrays used Promise.all) - iterate now guards the record branch with a plain-object prototype check, preventing class instances from being silently iterated via Object.entries - vitest coverage include expanded from src/typectl.ts to all src/**/*.ts (excluding specs and examples) so implementation modules are measured - Update README and JSDoc to reflect new toValue and iterate semantics - Add tests: sequential toValue for arrays and records, iterate skips class instances Made-with: Cursor
Made-with: Cursor
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.
Summary
toValueis now always sequential. Previously, array inputs ran callbacks concurrently viaPromise.all, making stateful async reductions non-deterministic (a footgun for anyone expectingreduce-like behaviour). All input types — arrays, records, and streams — are now processed one element at a time, so the accumulator is always updated in order.iteratenow rejects class instances as records. The record branch previously matched anytypeof === "object"value, silently runningObject.entrieson class instances and picking up their enumerable own properties. The check now requiresObject.getPrototypeOf(iterable) === Object.prototype(ornull), so only plain object literals andObject.create(null)objects are treated as records; class instances are skipped.Coverage config now measures real implementation.
vitestcoverage was scoped tosrc/typectl.ts(the barrel re-export), so reported line/branch numbers were meaningless. Theincludeglob is nowsrc/**/*.tswith specs and examples excluded, giving accurate coverage acrosswrap.ts,mappers.ts,iterate.ts, etc.Test plan
npm test— all 41 tests passtoValue is sequential and deterministic for arrays— verifies visit order and sumtoValue is sequential and deterministic for records— verifies visit order and sumiterate skips class instances— verifies empty output for a class instance inputnpm run test:coverageand confirm implementation modules appear in the reportMade with Cursor