Skip to content

refactor(linters): enable no-explicit-any and fix usages#44727

Draft
secustor wants to merge 11 commits into
renovatebot:mainfrom
secustor:refactor/oxlint-no-explicit-any
Draft

refactor(linters): enable no-explicit-any and fix usages#44727
secustor wants to merge 11 commits into
renovatebot:mainfrom
secustor:refactor/oxlint-no-explicit-any

Conversation

@secustor

Copy link
Copy Markdown
Member

Changes

  • Enables no-explicit-any for production code
  • Fixes where possible the usages and replaces them with concrete types, unknown or defaults in case of generics.

Context

Please select one of the following:

  • This closes an existing Issue, Closes: #
  • This doesn't close an Issue, but I accept the risk that this PR may be closed if maintainers disagree with its opening or implementation

AI assistance disclosure

Did you use AI tools to create any part of this pull request?

Please select one option and, if yes, briefly describe how AI was used (e.g., code, tests, docs) and which tool(s) you used.

  • No — I did not use AI for this contribution.
  • Yes — minimal assistance (e.g., IDE autocomplete, small code completions, grammar fixes).
  • Yes — substantive assistance (AI-generated non‑trivial portions of code, tests, or documentation).
  • Yes — other (please describe):

Documentation (please check one with an [x])

  • I have updated the documentation, or
  • No documentation update is required

How I've tested my work (please select one)

I have verified these changes via:

  • Code inspection only, or
  • Newly added/modified unit tests, or
  • No unit tests, but ran on a real repository, or
  • Both unit tests + ran on a real repository

The public repository:

secustor and others added 11 commits July 14, 2026 00:25
Enable the built-in typescript/no-explicit-any rule in oxlint.

Violation inventory at time of enablement: 589 total, of which 308 are
in *.spec.ts files and 6 in test/** helpers. Since spec violations
dominate and the test suite makes heavy intentional use of any, the
rule is turned off for **/*.spec.ts and test/** via the existing
spec-scoped override, matching how other test-only rule adjustments are
handled.

The remaining 275 violations in production code (lib/) and tools/
exceed the mechanical-fix threshold for this change, so the rule is
introduced at "warn" severity instead of "error" and no violations
are fixed here. This keeps 'pnpm oxlint' green while surfacing all
explicit any usages, allowing them to be burned down incrementally and
the severity raised to "error" afterwards.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Resolve .oxlintrc.json conflict keeping both sides' rules: this branch's
spec-scoped typescript/no-explicit-any off plus main's
vitest/consistent-test-it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RxHFNsSworLcv23xXk9Hk
Raise the built-in typescript/no-explicit-any from warn to error so new
explicit any usages are rejected. After merging main, 266 violations
remain, all in lib/** and tools/** production code; these are burned
down in the following commits.

The rule stays off in the spec/test override block: spec 'as any' on
object literals is already banned by renovate/prefer-partial-in-specs,
and the remaining spec usages are type annotations on mocks and helpers
where mock typing needs latitude.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RxHFNsSworLcv23xXk9Hk
Zod v4 defaults ZodType parameters to unknown with covariant variance,
so 'Schema extends ZodType' accepts the same schemas as the previous
'ZodType<any, any, any>' spelling. Rework getJson/getToml implementation
signatures to type schema args as ZodType<z.infer<Schema>> so arguments
flow to resolveArgs without any, and build the getToml response body
without mutating the string-typed response.

The two LooseArray/LooseRecord return types in schema-utils keep 'any'
with disable comments: zod declares Input covariantly, so unknown there
breaks .pipe() composition at call sites.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RxHFNsSworLcv23xXk9Hk
Replace explicit any in the platform layer with precise types:
- getJsonFile now returns Promise<unknown> across the Platform
  interface and all implementations; the three call sites that consume
  it assert the concrete config shape they expect.
- Empty-object config initializers use their real config type instead
  of "as any".
- Ad-hoc request body/options literals get inline structural types.
- bitbucket sanitizeReviewers and github handleBranchProtectionError
  type their error parameters structurally instead of any.
- Misc: PagedResult defaults to unknown, prStateMapping keyed by
  BbsRestPrState, getQueryString takes object, retry() is generic
  without any.

Part of the typescript/no-explicit-any burndown.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RxHFNsSworLcv23xXk9Hk
Burn down typescript/no-explicit-any in lib/modules/manager:
- Introduce a documented DefaultManagerData alias as the single place
  the managerData default type lives; the generic defaults in
  RangeConfig, PackageFile(Content), PackageDependency, Upgrade,
  UpdateDependencyConfig and PostUpdateConfig all use it. The alias must
  stay Record<string, any> for bidirectional assignability with each
  manager's concrete managerData interface (documented on the alias,
  covered by one scoped disable comment).
- Upgrade.currentRawValue drops its any override and inherits the
  string typing from PackageDependency.
- NpmManagerData/DenoManagerData lose their Record<string, any> index
  signatures; the actually-used extra fields (workspaces,
  npmrcFileName) are declared explicitly.
- maven: props plumbing is typed Record<string, MavenProp> end to end,
  removing the long-standing "wrong types here" casts, and the
  modelVersion sniff narrows XML nodes via instanceof.
- helm-requirements/helm-values/pipenv/npm yarn: parser results get
  structural types instead of any (schema migration remains renovatebot#9610).
- bazel-module: transformRulesImgCalls takes ResultFragment[].
- deps-edn: UnionToIntersection helper rewritten with unknown/void.

Part of the typescript/no-explicit-any burndown.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RxHFNsSworLcv23xXk9Hk
Burn down typescript/no-explicit-any in lib/modules/datasource and
lib/modules/versioning:
- Release.constraints is now (string | undefined)[] per constraint,
  documenting that undefined entries mean "no constraint declared" (the
  filtering code already special-cases them); this lets pypi drop its
  as-any cast without silently changing filtering behavior.
- npm npmrc parsing works on Record<string, unknown> with the existing
  isString guards instead of any.
- azure-pipelines-tasks comparator, conda paged query variables and the
  datasource logError helper get structural types.
- conan versioning: fixParsedRange returns SemVer[], cursor variables in
  findSatisfyingVersion are typed, and isLessThanRange coerces the
  optional loose-API result to boolean.
- maven versioning: matches() reducer is typed boolean.

Part of the typescript/no-explicit-any burndown.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RxHFNsSworLcv23xXk9Hk
Burn down typescript/no-explicit-any in lib/util:
- memory and package cache get() default their type parameter to
  unknown instead of any; the handful of untyped call sites now pass an
  explicit type. ChangeLogRelease.date/gitRef are widened to match the
  data actually cached (release timestamps can be null/undefined).
- git instrument wrapper: reset/push/pull/fetch use simple-git's own
  parameter and result types instead of any passthroughs.
- exec DataListener chunks are unknown; promises/yaml/split/
  vulnerability/merge-confidence helpers get precise structural types.
- gitea/forgejo closePR/closeIssue drop their unused http options
  parameter, which was being spread into the API body params.
- HttpOptions.body keeps `any` behind a documented disable comment: it
  must stay assignable to got's `body` union at the got boundary, which
  `unknown` is not.

Part of the typescript/no-explicit-any burndown.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RxHFNsSworLcv23xXk9Hk
Burn down typescript/no-explicit-any in lib/logger:
- Logger meta parameters are typed `object` instead of
  Record<string, any>: callers legitimately log typed interface values
  and arrays, which `object` admits while still rejecting primitives.
- sanitizeValue() takes and returns unknown, building a typed
  Record<string, unknown> result internally.
- BunyanNodeStream.write accepts string chunks too (the non-raw
  sanitizer path stringifies before writing).
- errSerializer/getContext/once helpers get precise types; OmitFn uses
  the never[]/unknown function supertype.
- The ProblemStream raw-stream registration documents its cast: bunyan's
  stream typing cannot express raw object streams.

Part of the typescript/no-explicit-any burndown.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RxHFNsSworLcv23xXk9Hk
Burn down typescript/no-explicit-any in lib/config and lib/workers:
- replaceArgs() becomes a single generic that returns the input shape;
  the five overloads collapse into one truthful signature.
- mergeChildConfig() constrains to object (callers pass typed configs)
  and works on Record<string, unknown> clones internally.
- Preset data plumbing (fetchPreset, group presets, npm presets) uses
  the indexable Preset type instead of any.
- configFileParsed is RenovateConfig across repo-init/reconfigure; the
  package.json `renovate` field is extracted via a typed intermediate.
- CLI/env option coercion and parsed-config records use unknown values.
- Misc: getDefault() returns unknown, host-rules migration builds typed
  HostRules, flatten/branchify/generate/commit replace their as-any
  casts, CVSS vector parsing drops a decorative any annotation.

Part of the typescript/no-explicit-any burndown.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RxHFNsSworLcv23xXk9Hk
Burn down the final typescript/no-explicit-any violations in tools/**:
- docs/config.ts: genTable works on [string, unknown] tuples and the
  option element records use unknown values; the experimental and
  deprecation message helpers declare the fields they read.
- docs/schema.ts: introduce a documented JsonSchemaNode alias (one
  scoped disable) for the ad-hoc JSON Schema tree that is assembled
  through dynamic access; regenerating the schemas produces no diff.
- mkdocs.ts: prepareDocs declares its commander options shape.

This brings the branch to zero no-explicit-any violations.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RxHFNsSworLcv23xXk9Hk
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