Skip to content

fix(fs): expose iterator helpers on walk/walkSync and expandGlob/expandGlobSync#7136

Open
fibibot wants to merge 2 commits into
mainfrom
orch/issue-62
Open

fix(fs): expose iterator helpers on walk/walkSync and expandGlob/expandGlobSync#7136
fibibot wants to merge 2 commits into
mainfrom
orch/issue-62

Conversation

@fibibot
Copy link
Copy Markdown

@fibibot fibibot commented May 14, 2026

Summary

walk, walkSync, expandGlob, and expandGlobSync are generator functions, but their return-type annotations widened the type to (Async)IterableIterator<WalkEntry>, hiding the ES2025 iterator helpers (.map, .filter, .take, …) at the type level. The runtime objects do have those helpers (on the sync side), so the original repro

const a = walkSync(".");
const b = a.map((v) => v.name);
//          ^^^ Property 'map' does not exist on type 'IterableIterator<WalkEntry>'.

was a type-only bug.

This PR changes the annotations to Generator<WalkEntry> /
AsyncGenerator<WalkEntry> for all four functions so callers can chain
helpers without widening, and the async pair is forward-compatible for
when async iterator helpers ship in the standard library.

Note: walk and walkSync need an explicit return type (TS7023 — they
reference themselves recursively), so the annotations are tightened
rather than dropped entirely.

Test plan

Regression tests are co-located in fs/walk_test.ts and
fs/expand_glob_test.ts. The sync tests exercise .map(...).toArray()
at both type-check and runtime; the async tests assert that
AsyncGenerator shape is preserved (no async iterator helpers exist at
runtime yet, so they just exercise .next() / .return()).

  • deno fmt --check
  • deno lint
  • deno run -A _tools/check_docs.ts
  • New tests pass: walkSync()/expandGlobSync() returns a generator that exposes iterator helpers, walk()/expandGlob() returns an async generator
  • Original repro from fs: walkSync returns a type without iterator helpers #7099 type-checks

Closes #7099
Closes bartlomieju/orchid-inbox#62

…`/`expandGlobSync`

The four generator functions in `@std/fs` were annotated with the
`IterableIterator<WalkEntry>` / `AsyncIterableIterator<WalkEntry>`
return types, which widen the actual `Generator` / `AsyncGenerator`
runtime type and hide the ES2025 iterator helpers (`.map`, `.filter`,
`.take`, etc.) at the type level.

Switch the annotations to `Generator<WalkEntry>` /
`AsyncGenerator<WalkEntry>` so callers can chain helpers without
widening, e.g. `walkSync(".").map((v) => v.name)`.

Closes #7099
@CLAassistant
Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@github-actions github-actions Bot added the fs label May 14, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented May 14, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 94.61%. Comparing base (6510612) to head (384a722).

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #7136   +/-   ##
=======================================
  Coverage   94.61%   94.61%           
=======================================
  Files         634      634           
  Lines       51822    51826    +4     
  Branches     9336     9348   +12     
=======================================
+ Hits        49029    49035    +6     
+ Misses       2218     2216    -2     
  Partials      575      575           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

The previous commit added `Generator<WalkEntry>` annotations and tests that
exercise `.map(...).toArray()`. Both regressed on Deno v1.x (TypeScript 5.5,
which predates iterator helpers in `lib.es2025.iterator.d.ts`):

- `expandGlob` / `expandGlobSync` ended with `yield* currentMatches`, where
  `currentMatches` is `WalkEntry[]`. Array's iterator declares `TNext` as
  `undefined`, but the outer `Generator<WalkEntry>`'s `TNext` defaults to
  `unknown`, so TS 5.5 reports TS2766. Newer TS widens the array iterator to
  `unknown` and the call type-checks. Replace the delegation with an explicit
  `for ... yield` loop so it compiles on both.
- The new tests called `.map(...).toArray()` on the returned iterator, which
  TS 5.5 rejects (no iterator helpers in lib). Switch to a type-level
  assertion: `const iter: Generator<WalkEntry> = walkSync(...)`. This still
  enforces the regression — `Generator<T>` requires the `.return()`/`.throw()`
  methods that `IterableIterator<T>` leaves optional, so the assignment fails
  if the return type widens back — but compiles on every TS version where
  `Generator<T>` is defined.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fs: walkSync returns a type without iterator helpers

2 participants