Skip to content

refactor: eliminate any types in core (non-clis) files#886

Merged
jackwener merged 1 commit intomainfrom
claude/festive-williams
Apr 8, 2026
Merged

refactor: eliminate any types in core (non-clis) files#886
jackwener merged 1 commit intomainfrom
claude/festive-williams

Conversation

@jackwener
Copy link
Copy Markdown
Owner

Summary

Replace explicit any with unknown + narrowing or concrete types across src/ core files (non-clis/**). Reduces core any count from ~51 → 9, where the remaining 9 are explicitly documented cross-boundary exceptions.

Changes

Mechanical error-handler cleanup (uses existing getErrorMessage() from src/errors.ts):

  • src/cli.ts, plugin.ts, external.ts, doctor.ts, cascade.ts, download/index.ts, download/media-download.tscatch (err: any)catch (err) + getErrorMessage(err) or instanceof Error narrowing.

Pipeline steps — typed params with per-step interfaces:

  • src/pipeline/steps/intercept.tsInterceptParams interface, signature uses unknown.
  • src/pipeline/steps/tap.tsTapParams interface.
  • src/pipeline/steps/download.tsDownloadParams + DownloadedItem types, items typed as Array<Record<string, unknown>>.

Injected browser scripts — structural types at the TS boundary (erased at runtime, so .toString() output is unchanged):

  • src/scripts/store.tsPiniaStore / VuexModule / VueApp.
  • src/scripts/framework.tsVueAppEl / FrameworkWindow.

Test files — precise structural casts replacing as any:

  • src/browser.test.ts, engine.test.ts, snapshotFormatter.test.ts, pipeline/executor.test.ts.

Incidental fix: src/cascade.tsresult.success = resp?.ok && resp?.hasData could assign undefined to a boolean field (masked by any); now !!(...).

Deferred (documented with eslint-disable + rationale)

  • src/types.tsIPage.evaluate/snapshot/tabs/... still return Promise<any>. These cross the untyped-JS boundary (in-page eval results, extension responses). Tightening to unknown cascades into ~450 narrowing sites across src/clis/**.
  • src/registry.tsCommandArgs = Record<string, any>. kwargs are destructured across all adapters with the same cascade.

Both now carry explicit comments so new any can't be added silently. Cleanup across clis/** is a separate follow-up.

Test plan

  • npx tsc --noEmit — clean
  • npx vitest run unit + integration (excluding tests/e2e/**, tests/smoke/**) — 260/260 pass
  • Verified pre-existing e2e/smoke failures are not introduced by this change (stashed + reran on clean HEAD, same failures)
  • Confirmed no non-clis/ any occurrences remain beyond the 9 documented exceptions

@jackwener jackwener force-pushed the claude/festive-williams branch 3 times, most recently from 67025fe to c915959 Compare April 8, 2026 14:49
Replace explicit `any` with `unknown` + narrowing or concrete types across
all core src/ files (non-`clis/**`). Core drops from ~60 `any` occurrences
to a handful of documented, unavoidable boundaries.

Mechanical error-handler cleanup (uses getErrorMessage() from errors.ts):
  - cli.ts, cascade.ts, download/*.ts, external.ts, plugin.ts, doctor.ts
    — catch (err: any) → catch (err) + getErrorMessage(err)

Pipeline steps — typed params with per-step interfaces:
  - pipeline/steps/intercept.ts — InterceptParams, signature uses unknown
  - pipeline/steps/tap.ts       — TapParams
  - pipeline/steps/download.ts  — DownloadParams + DownloadedItem
    (ytdlp_args is now coerced via String(v) for defence-in-depth)

Probe / boundary typing:
  - cascade.ts — FetchProbeResponse interface; also fixes a latent bug
    where result.success could be assigned undefined (masked by any)
    by wrapping with !!(…)

Browser-side injected scripts — structural types at the TS boundary
(types stripped by tsc emit before .toString() runs, runtime unchanged):
  - scripts/store.ts     — PiniaStore / VuexModule / VueApp
  - scripts/framework.ts — VueAppEl / FrameworkWindow

Runtime detection:
  - runtime-detect.ts — BunGlobal interface; getRuntimeVersion reads Bun
    into a local to avoid non-null assertions.

Test files — precise structural casts replacing `as any`:
  - browser.test.ts             — `{ _state: string }` cast for private
                                   state; full DaemonStatus shape for
                                   the getDaemonHealth mock
  - browser/dom-helpers.test.ts — globalThis as Record<string, unknown>
  - browser/cdp.test.ts         — (...args: unknown[]) in mock handlers
  - runtime-detect.test.ts      — matches runtime-detect.ts BunGlobal
  - output.test.ts              — logSpy.mock.calls typed with unknown[]
  - engine.test.ts, snapshotFormatter.test.ts, pipeline/executor.test.ts
    — narrow structural casts / removed stale any casts

Verification:
  - npx tsc --noEmit: clean
  - npx vitest run (excluding e2e/smoke): 1415 passed, 1 skipped
@jackwener jackwener force-pushed the claude/festive-williams branch from c915959 to 93de3af Compare April 8, 2026 14:57
@jackwener jackwener merged commit 810547c into main Apr 8, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant