refactor: reduce EXPECTED_ANY in stats hook and printer types#21198
Conversation
Recover the real inner-hook and result types in StatsFactory and StatsPrinter via HookMap/Hook inference instead of EXPECTED_ANY for the level-hook caches and _forEachLevel result generics.
Cast the compilation printer to its real signature like the sibling asset/issuer/profile dispatch loops; the remaining loops dispatch over heterogeneous printer unions that have no callable common signature.
Replace the EXPECTED_ANY FactoryData typedef in _forEachLevelWaterfall and _forEachLevelFilter with a generic D template defaulting to EXPECTED_ANY, so the caller's item type flows through; also fixes _forEachLevelFilter declaring its return as the hook result type (boolean | void) instead of the item type.
Cast the heterogeneous printer dispatches to SimplePrinter instead of a whole-function EXPECTED_ANY, so the printer context and return value are type-checked; only the printed value stays EXPECTED_ANY.
countWithChildren only reads .length, so type getItems as
() => { length: number } instead of a generic T[]; this lets the
warnings counter return its real Error[]/StatsError[] values and drops
the EXPECTED_ANY[] cast that previously bridged them.
🦋 Changeset detectedLatest commit: 50dcb92 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
This PR is packaged and the instant preview is available (b15a94c). Install it locally:
npm i -D webpack@https://pkg.pr.new/webpack@b15a94c
yarn add -D webpack@https://pkg.pr.new/webpack@b15a94c
pnpm add -D webpack@https://pkg.pr.new/webpack@b15a94c |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #21198 +/- ##
==========================================
- Coverage 92.70% 92.69% -0.01%
==========================================
Files 588 588
Lines 64118 64120 +2
Branches 17797 17798 +1
==========================================
- Hits 59440 59438 -2
- Misses 4678 4682 +4
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
The no-filter branch of warningsCount was guarded by `!warningsFilter && warningsFilter.length === 0`, which is never true because warningsFilter is always normalized to an array. Drop the dead `!warningsFilter` term so the empty-filter case returns the raw warnings for counting instead of running factory.create().filter(); warningsCount is unchanged (stats snapshots pass).
Merging this PR will improve performance by 30.5%
|
| Mode | Benchmark | BASE |
HEAD |
Efficiency | |
|---|---|---|---|---|---|
| ❌ | Memory | benchmark "side-effects-reexport", scenario '{"name":"mode-development-rebuild","mode":"development","watch":true}' |
766.9 KB | 1,205.2 KB | -36.37% |
| ❌ | Memory | benchmark "many-modules-esm", scenario '{"name":"mode-production","mode":"production"}' |
7.8 MB | 10 MB | -22.59% |
| ⚡ | Memory | benchmark "asset-modules-inline", scenario '{"name":"mode-development-rebuild","mode":"development","watch":true}' |
1,293.8 KB | 324.5 KB | ×4 |
| ⚡ | Memory | benchmark "css-modules", scenario '{"name":"mode-production","mode":"production"}' |
10 MB | 6.8 MB | +47.68% |
Tip
Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.
Comparing claude/stats-expected-any-7e1x0g (50dcb92) with main (0db8bbb)
Covers the warnings-count branch fixed in this PR: emits warnings with no warningsFilter and shows only warningsCount, asserting the raw count is reported.
Summary
lib/stats/usedEXPECTED_ANY(alias forany) in many spots where a real type is recoverable. This PR tightens the recoverable ones while keepingEXPECTED_ANYonly where it is genuinely existential:StatsFactory/StatsPrinterhook plumbing: infer the real inner-hook and result types for the level-hook caches and_forEachLevel*generics (also fixes theresultcache being typed asSyncBailHookinstead ofSyncWaterfallHook).StatsFactorylevel helpers: thread a@template [D=EXPECTED_ANY]item type through_forEachLevelWaterfall/_forEachLevelFilter(this also fixes_forEachLevelFilterdeclaring its return as the hook resultboolean | voidinstead of the item type).DefaultStatsPrinterPlugindispatch loops: type the compilation loop with its real signature and the remaining loops asSimplePrinter<EXPECTED_ANY, …>so the printer context and return value are checked (only the printed value staysEXPECTED_ANY).countWithChildren: it only reads.length, so it now takes() => { length: number }instead of a genericT[], dropping theEXPECTED_ANY[]cast that bridgedError[]/StatsError[].While dropping that cast, the
warningsCountno-filter branch was found to be dead: it was guarded by!warningsFilter && warningsFilter.length === 0, which is never true becausewarningsFilteris always normalized to an array. The guard is corrected towarningsFilter.length === 0, so the empty-filter case returns the raw warnings for counting instead of runningfactory.create(...).filter(...)— a small perf win with an unchangedwarningsCount(stats snapshots pass).The remaining
EXPECTED_ANYusages are intentional: plugin-extensible stats records (Known* & Record<string, EXPECTED_ANY>), existential generics (Comparator,GroupConfig), dynamic factory/printer data, and runtime-string hook dispatch. No public type surface (types.d.tsunchanged).What kind of change does this PR introduce?
refactor (primarily a type cleanup; includes one small
perffix to the dead warnings-count branch surfaced by the refactor)Did you add tests for your changes?
Yes — added
test/statsCases/warnings-countassertingwarningsCountis reported without awarningsFilter(covering the fixed branch). The type changes are also exercised by the existingtest/StatsTestCases(now 132 cases, all passing).Does this PR introduce a breaking change?
No.
If relevant, what needs to be documented once your changes are merged or what have you already documented?
n/a
Use of AI
AI (Claude Code) was used to inventory the
EXPECTED_ANYusages, implement the type changes and the warnings-count fix, add the test, and verify each step withyarn tscand the stats tests; all changes were reviewed.